2015-05-21 2 views
2

У меня есть приложение, которое реализовано на C++. В приложении есть API-интерфейс плагина, в котором вы можете скомпилировать dll и поместить их в определенное место, и они будут автоматически загружены в хост-приложение при его запуске, настраивая функциональность.Как реализовать C++ ATL/COM EXE-сервер через плагин DLL

Есть ли способ скомпилировать dll с использованием ATL таким образом, чтобы плагин dll «преобразовал» приложение в COM-сервер exe.

Следующий код атрибута ATL будет работать, если бы это был сервер InProc, но это не InProc:

[module(dll, ...)]; 

Для сервера ехе мне нужно:

[module(exe, ...)]; 

Однако компилятор дает я ошибаюсь в этом, потому что я на самом деле собираю dll, поэтому я вынужден использовать следующее:

[module(unspecified, ...)]; 

Это компилируется нормально, и MSDN для «неопределенного» варианта говорит:

Отключает инъекцию АТЛИ код, связанный с атрибутом модуля: в инъекции класса ATL модуля, глобальный экземпляр _AtlModule и запись функций точечных. ... атрибутов в проекте.

Итак, во-первых, возможно ли сделать exe на COM-сервер через плагин dll? Во-вторых, если да, то какой будет правильный «класс модуля ATL, глобальный экземпляр _AtlModule и функции ввода», чтобы добавить в проект, чтобы он работал правильно.

  • Приложение является стандартным приложением Windows, поэтому его основной точкой ввода является функция WinMain().
  • Плагин dll будет задерживаться, , так что он не мгновенно загружается exe.

Я немного любитель COM, а документация COM/ATL настолько глубока и настолько обширна и настолько широка, что я даже не знаю с чего начать.

+0

Итак, у вас есть два приложения: A (с API-интерфейсом плагина) и B (что делает забавные вещи). Вы хотите написать DLL-плагин для A, который вызывает B. Это правильно? Если да, то вы хотите сделать B COM-сервером exe, а затем написать отдельную DLL-плагин для A, который CoCreateInstance B (как сервер, не обслуживающий процесс), а затем вызывает B. –

+0

Нет, это наоборот вокруг. У меня есть приложение A (с API-интерфейсом плагина) и B. Я хочу написать DLL-плагин для A, который превращает A в COM-сервер exe, так что B может вызывать CoCreateInstance A как сервер вне процесса. –

ответ

1

Атрибуты расширены в код C++ (вы можете изменить настройку в настройках проекта и, кстати, добавить этот сгенерированный код в файлы для просмотра). [module(exe, ... получает вас CAtlExeModuleT как дополнительный базовый класс для наследования, затем [module(dll, ... получает вас CAtlDllModuleT. Однако разница не только в базовом классе, и это объясняет, почему вы не можете так легко переключаться.

В этом проблема: приписанный код C++ однажды выглядел круто, но впоследствии был устаревшим. Он по-прежнему строится для создания устаревших проектов, но от него следует четко следовать.

Если проект относительно невелик, лучше всего было бы избавиться от атрибутов. Это вполне выполнимо, так как вы можете быстро начать с расширенного неприсоединенного кода, созданного препроцессором. С другой стороны, это может быть не так просто, как кажется, поскольку атрибуты помогли сделать COM, не думая слишком много об IDL-файлах, о том, как они встроены в проект и т. Д. Если вы можете позволить использовать зачищенные атрибуты, вы хотите это сделать.

Тогда второй шаг - понять разницу между сервером ATL DLL и сервером ATL EXE. Самый простой способ - создать два пустых проекта с помощью мастера и сравнить код. Вам нужно будет отразить ту же самую разницу в вашем проекте, конвертируя его из DLL в EXE. Понимая различия, может случиться так, что проще всего будет использовать новый проект ATL EXE и импортировать соответствующие файлы исходного кода из старого атрибутированного проекта.

Если вы предпочитаете оставаться с атрибутами, возможно, вы хотите в любом случае начать с пустых проектов, однако, я полагаю, вам нужна старая Visual Studio, потому что эта опция была убрана/скрыта довольно давно. Чтобы создать новый атрибутивный проект, вам понадобится, вероятно, VS 2005 или 2008.

2

вид делайте то, что вы просите (добавьте поддержку COM для exe через стороннюю поддержку), но это будет быть сложным, и много инструментария вам не поможет.

Я работаю над вторым изданием ATL Internals, в котором объясняется, что ATL делает для вас под обложкой.

Все серверы COM должны поддерживать регистрацию, должны выставлять объект класса и управлять его временем жизни.

Мы собираемся сыграть немного быстро & на регистрационной части, так как стандартный метод вызывает исполняемый файл с некоторыми вариантами командной строки, которые явно не сработают для вас. У вас может быть ваша DLL-модуль плагина автоматически зарегистрировать CLSID в пользовательском улье (подробнее см. this question) - это позволит избежать проблем с повышением. Регистрация немного сложна, так как вам нужно установить регистрационные ключи для exe-сервера, но сделать это из dll.

Ваш плагин вызывает CoRegisterClassObject, чтобы открыть объект класса при загрузке плагина и вызвать CoRevokeClassObject, когда плагин выгружен или приложение завершается.

Обратите внимание, что вам необходимо вызвать CoRegisterClassObject «скоро» после запуска exe.

Управление жизненным циклом для серверов EXE немного быстро & свободно - вы можете (или не можете) ухаживать за тем, чтобы ваше приложение-хост выгрузилось при отпускании последней ссылки.

После того, как вы внедрили это, вы можете без проблем использовать CCOMObject ATL, а I верьте, вы можете использовать карту объектов ATL для CoRegisterClassObject.