Работа с MS Word Interop (RCW) через отражение
От: Eugene_asoiu  
Дата: 19.03.10 10:31
Оценка:
Есть задача: оптимизировать работу с MS Word по времени выполнения. Работа с Word построена через InvokeMember, т. е. через позднее связывание. Под профайлером было выявлено, что 90% времени занимает обращения к Property классов Word, т. е. такие вызовы:
dispObj.GetType().InvokeMember("%property_name%", BindingFlags.GetProperty, null, dispObj, null);

Напрямую использовать Interop сборку не представляется возможным, т. к. необходима поддержка нескольких версий Word.
В MSDN нашел, что
Type.GetTypeFromProgID("Word.Application");

возвращает тип Microsoft.Office.Interop.Word.ApplicationClass сборки, которая в находится в GAC на пользовательской машине (конечно если установлены .NET Framework и одна из версий MS Office).
Появилась мысль ускорить работу с Word через invoking of PropertyInfo. Практика показала, что это работает быстрее чем InvokeMember, но вот только есть одно НО, которое ставит крест на всей идее (по крайней мере у меня с MS Word 2007).
Interop класс не видно, если брать проперти Documents у Word.ApplicationClass, т. е я смотрю под дебаггером и вижу только System._ComObject. С которым ничего не поделаешь и найти через отражение его проперти нельзя. Но если через InvokeMember взять у documents какой нибудь документ, то он будет класса Microsoft.Office.Interop.Word.DocumentClass. В TypeLib Word посмотрел. Как раз какие классы там описаны для таких я только и могу получить interop классы, а вот для интерфейсов (типа Word.Documents) не могу (((.
object wordApp = Activator.CreateInstance(Type.GetTypeFromProgID("Word.Application")));
Type documentsType = a.GetType("Microsoft.Office.Interop.Word.Documents");
object documents = null;
PropertyInfo propDocuments = wordApp.GetType().GetProperty("Documents");
documents = propDocuments.GetGetMethod().Invoke(wordApp, null);
finally
{
wordApp.GetType().InvokeMember("Quit", BindingFlags.InvokeMethod, null, wordApp, null);
}

Help, please.
com interop microsoft office reflection
Re: Работа с MS Word Interop (RCW) через отражение
От: Аноним  
Дата: 19.03.10 14:21
Оценка:
в 4й версии нета есть новый тип dynamic — он как раз и предназначен для работы в Interop — посмотрите в инете
Re[2]: Работа с MS Word Interop (RCW) через отражение
От: Eugene_asoiu  
Дата: 20.03.10 13:02
Оценка:
Здравствуйте, Аноним, Вы писали:

А>в 4й версии нета есть новый тип dynamic — он как раз и предназначен для работы в Interop — посмотрите в инете


К сожалению, нет возможности использовать .NET версии более 2.0.
Re: Работа с MS Word Interop (RCW) через отражение
От: Jolly Roger  
Дата: 20.03.10 16:00
Оценка:
Здравствуйте, Eugene_asoiu, Вы писали:

E_>Под профайлером было выявлено, что 90% времени занимает обращения к Property классов Word


Львиную долю у Вас занимают "походы" из Вашего процесса в Word и обратно, всё остальное по сравнению с этим — сущие пустяки. Даже переход на раннее связывание не даёт существенного прироста. Единственный способ получить реальное ускорение — перенести большую часть работы в сам Word и забирать результат максимально большим куском, сократив до минимума межпроцессные вызовы. Это можно сделать двумя способами: либо написать макросы, выполняющие всю работу, либо один макрос, загружающий в Word Ваш инпроцессный COM-объект. Тогда этот COM-объект будет выполнять основную работу, а Ваше приложение — давать ему команду и забирать результаты.

Несколько лет назад я использовал оба способа, первый с Word'ом, а а второй с AutoCAD'ом. Оба дали выигрыш на порядок и более.
"Нормальные герои всегда идут в обход!"
Re: Работа с MS Word Interop (RCW) через отражение
От: vdimas Россия  
Дата: 21.03.10 01:53
Оценка:
Здравствуйте, Eugene_asoiu, Вы писали:

E_>Есть задача: оптимизировать работу с MS Word по времени выполнения. Работа с Word построена через InvokeMember, т. е. через позднее связывание. Под профайлером было выявлено, что 90% времени занимает обращения к Property классов Word, т. е. такие вызовы:

E_>
E_>dispObj.GetType().InvokeMember("%property_name%", BindingFlags.GetProperty, null, dispObj, null);
E_>


Закешируй DISP_ID для каждого св-ва, будет быстрее (там простейший класс-хелпер на десяток строк). Дополнительно можно получить IDispatch, и дергай его похожей сигнатурой, будет еще быстрее.
Но ты не надейся на серьезные ускорения, тебе профайлер все-равно до 90% показывать будет, т.к. Word — это out of proc server, т.е. твои вызовы идут в другой процесс и обратно. Действительно ускорить можно если попросить c "той" стороны VBE, создать "там" временный модуль с требуемыми процедурами, и уже вызвать их на "той" стороне для каких-то осмысленных задач, ну или даже чтобы просто зачитать требуемый набор св-в в массив и вернуть за один раз. Одним словом, чем меньше "туда-сюда", тем эффективнее.

E_>Напрямую использовать Interop сборку не представляется возможным, т. к. необходима поддержка нескольких версий Word.


Да и не даст это особого ускорения, так что не парься.

Далее, Visual Studio невозможно посмотреть св-ва объекта через IDispatch, так что залезай в Word VBA, напиши в основном модуле текущего документа 3 строки:
sub s

end sub


Одна из трех — пустая. Прямо в ней экспериментируй, т.е. пиши что хошь. Пошаговое исполнение — F8, ничего компилировать не надо, даже если есть ошибки, можно пошагово исполнять до ошибочной строки, потом исправить и шагать дальше. Через контекстное меню переноси курсор исполнения куда надо. По Shift+F9 добавь переменные в watch list, и вот тут-то VBA покажет все св-ва, даже те, которые доступны только через IDispatch.

Для "борьбы" с офисом приведенный сценарий — наиболее эффективный, т.к. дока по программным объектам ворда весьма скудная, и если опыта с ним маловато, то единственная возможность не встрять на банальнейших вещах — эта вот такая живая отладка алгоритмов в "родной" среде. Когда отладишь — переноси куда хошь.
Re[2]: Работа с MS Word Interop (RCW) через отражение
От: Jolly Roger  
Дата: 21.03.10 03:46
Оценка:
Здравствуйте, vdimas, Вы писали:


V>так что залезай в Word VBA, напиши в основном модуле текущего документа 3 строки:


Ещё можно добавить, что в офисе есть возможность записи макросов. Включили запись, выполнили несколько действий вручную, остановили запись. Далее открываем этот макрос и смотрим, что он там понаписал. Это помогает легко и быстро разобраться с его объектной моделью.
"Нормальные герои всегда идут в обход!"
Re: Работа с MS Word Interop (RCW) через отражение
От: vecs Россия  
Дата: 22.03.10 09:26
Оценка:
Здравствуйте, Eugene_asoiu, Вы писали:

E_>Напрямую использовать Interop сборку не представляется возможным, т. к. необходима поддержка нескольких версий Word.


А одно другому не мешает.
Вот, например, AWordReport работает cо всеми версиями Word, начиная с Office 97. И делает он это именно через Interop.
word interop
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.