Re: Маршалинг и typelib
От: Jolly Roger  
Дата: 07.09.10 12:14
Оценка: 12 (4)
Здравствуйте, Andrey.Katkov, Вы писали:

Надеюсь, про функцию RegisterTypeLibForUser Вы знаете?

Если это по каким-то причинам не подходит, то маршалинг на основе библиотеки типов без регистрации самой библиотеки обеспечить несложно, но это потребует использования недокументированного API (оно, кстати упомянуто по приведённой Вами ссылке, это функции CreateProxyFromTypeInfo и CreateStubFromTypeInfo). Попробую расписать поэтапно.

Сначала пишите фабрику Proxy/Stub, реализующую интерфейс IPSFactoryBuffer, ну и IUnknown, разумеется . Далее регистрируете её как объект класса, обычным образом, через CoRegisterClassObject с флагами CLSCTX_INPROC_SERVER и REGCLS_MULTIPLEUSE, это важно. Затем регистрируете её-же как фабрику Proxy/Stub вызовом CoRegisterPSClsid. Ну и теперь подсистема COM будет вызывать эту фабрику для создания Proxy и Stub, а Вы в реализации методов IPSFactoryBuffer просто вызываете вышеупомянутые функции.

Эта схема работает. Я, например, создавал один экземпляр фабрики на экземпляр библиотеки, в качестве CLSID использовал IID интерфейса, а в IPSFactoryBuffer.CreateProxy и IPSFactoryBuffer.CreateStub уже непосредственно запрашивал ITypeInfo преред вызовом CreateProxyFromTypeInfo и CreateStubFromTypeInfo соответственно.

PS Дополнительный бонус Так как ITypeInfo можно собрать прямо в рантайм, то можно вообще обойтись без библиотеки типов.
"Нормальные герои всегда идут в обход!"
Маршалинг и typelib
От: Andrey.Katkov  
Дата: 07.09.10 07:32
Оценка:
Всем читающим — доброго дня!

Есть задача: сделать обновляемый COM-компонент, который не надо перерегистрировать в системе для использования. Поясню на примере своей пробной реализации.

При инсталяции я один раз регистрирую некоторую "пустую" COM-длл (ограничение однократности связано с юзабилити под Vista и Seven — не хочется повторных UAC окошек и телодвижений для пользователя). Потом выходит новая версия этой длл в которой меняется интерфейс и реализация — но регистрировать ничего нельзя. Новая длл-ка скачивается и кладётся в некоторую папку рядом с зарегистрированной.

..
1.dll 
1.0.9.0
    1.dll


Зарегенная длл-ка при обращении к ней находит и подгружает последнюю версию длл (из папки 1.0.9.0) и фактически вызывает её методы DllGetClassObject и DllCanUnloadNow.

Для базовых сценариев схема работает. Затык при попытке обратиться к отмаршаленному в другой процесс через "Running Object Table" интерфейсу из такой длл. Падает при попытке вызова какого либо метода — typelib зареген в промежуточной длл-ке, и видимо не отрабатывает typelib-маршалинг (терминология из статьи http://www.rsdn.ru/article/com/marsh.xml
Автор(ы): Чистяков В.Ю.
).
Пока вижу решение в создании промежуточной же proxy/stub DLL — т.е. делать что-то наподобии:

..
1.dll 
1PS.dll
1.0.9.0
    1.dll
    1PS.dll


Вопрос к специалистам COM:
1) Как можно элегантней решить поставленную задачу? Данный компонент будет использоваться другими моими же компонентами, если это имеет значение.
2) Как в рамках моей схемы разрулить ситуацию с маршаленгом — можно ли "заставить" брать typelib из конкретного файла ("1.0.9.0\1.dll") а не через реестр из моей "промежуточной" длл. (Например в IDispatchImpl используются LoadRegTypeLib и LoadTypeLib в зависимости от настроек).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.