Я смог использовать манифесты, и особенно задачу MSBuild GenerateApplicationManifest, чтобы наше основное приложение использовало изолированный COM. Я могу создать все COM-объекты, реализованные в DLL, которые мне нужны, без необходимости регистрации DLL на моей клиентской машине. Но, я жадный ...Потребление EXE-сервера через квазиизолированный COM
В нашем наборе приложений также есть отдельные приложения, которые вызывается через COM, как правило. Для них сказано, что вы не можете использовать EXE для EXE изолированного COM. Строго говоря, это правда, но я получил 90% пути, и на других форумах я видел, как другие давали подсказки, чтобы проложить остальную часть пути.
Для моего EXE-сервера у меня есть запись в манифесте с именем EXE-сервера и подзаголовкой в этой записи, так что, когда ATL-сервер вызывает LoadRegTypeLib()
, вызов будет успешным. Это работает.
Конечно, сложная часть является то, что вы не можете поставить запись для сервера EXE в клиентском приложении манифеста и ожидать CoCreateInstance()
добиться успеха (путем запуска EXE-сервера и делать все другие вещи COM делает.)
Я могу подделать совсем немного, потому что я знаю, что запускать EXE-сервер. Я могу позвонить CreateProcess()
, а затем вызвать WaitForInputidle()
в клиентском приложении, чтобы мой сервер был готов для CoCreateInstance() в клиентском приложении.
Если я звоню CoCreateInstance()
и запрашиваю интерфейс IDispatch
в клиентском приложении, вызов выполняется успешно, и я могу позвонить Invoke()
и все будет работать.
Сейчас здесь идет жадная часть ...
Это все хорошо, что IDispatch работает, но я хочу, чтобы иметь возможность звонить через мои двойственные интерфейсы, полученных от IDispatch. Я хочу сделать это, потому что у меня много написано кода, и синтаксис проще, и обработка исключений уже существует.
Однако, когда я вызываю QueryInterface()
для двойного интерфейса на моем интерфейсе IDispatch
, я получаю возврат E_NOINTERFACE. Я установил точки останова в моем объекте сервера ATL на сервере EXE и могу подтвердить, что на стороне сервера он находит интерфейс и возвращает S_OK. Таким образом, похоже, что интерфейс не может быть перенаправлен обратно клиенту.
Итак, вопрос в том, как я могу получить QueryInterface()
для моего пользовательского/двойного интерфейса для успеха? Я пробовал различные комбинации использования <comInterfaceProxyStub>
и <comInterfaceExternalProxyStub>
в манифесте клиента (и манифеста сервера), чтобы попытаться маршалировать интерфейс, но я все еще вижу возврат E_NOINTERFACE
в моем клиенте.
Я видел комментарий Ханса Пассана от нескольких лет назад на другом форуме о том, что, возможно, понадобится отдельная DLL для прокси-сервера/заглушки для маршалинга интерфейса, но деталей было мало.
Возможно ли это решить в бесплатном для регистрации контексте? Нужно ли создавать прокси/заглушку? Если да, то как выглядят записи манифеста в моем клиентском приложении (и/или серверное приложение, и/или прокси/заглушка DLL)?
Для моего простого тестового приложения у меня есть только один объект с одним двойным интерфейсом. В вашем примере у вас есть элементы с (в пределах ) и (в пределах ). Нужна ли мне одна запись? Я использовал ATL для генерации EXE с помощью PS DLL, и интересно, что CLSID для прокси-сервера (найденный при проверке реестра) совпадает с CLSID для интерфейса. –
Вам нужно всего лишь использовать один из подходов. Если ваш двойной интерфейс использует стандартную маршалинг (прокси/заглушку DLL), используйте 'comInterfaceProxyStub'. Если ваш двойной интерфейс использует маршалинг библиотеки типов (файл TLB или встроенный в ресурс DLL) или любой другой зарегистрированный (неизолированный) прокси-сервер, используйте 'comInterfaceExternalProxyStub'. Я отредактирую ответ, чтобы отразить это двумя отдельными примерами. – acelent
Поскольку вы указываете, что CLSID прокси/заглушки совпадает с IID, (скорее всего, это должно быть так, что вы используете стандартное маршалинг, так что у вас есть прокси/заглушка DLL. Используйте 'comInterfaceProxyStub'. – acelent