如何通过插件DLL实现C ++ ATL / COM EXE服务器

时间:2015-05-21 20:24:58

标签: c++ winapi dll com atl

我有一个用c ++实现的应用程序。该应用程序有一个插件API,您可以在其中编译dll并将它们放入某个位置,它们将在启动时自动加载到主机应用程序中,自定义功能。

有没有办法使用ATL编译一个dll,插件dll会将应用程序“转换”为COM exe服务器。

如果它是inproc服务器,则以下ATL属性代码可以工作,但它不是inproc:

[module(dll, ...)];

对于我需要的exe服务器:

[module(exe, ...)];

但是,编译器给出了我的错误,因为我实际上正在编译一个dll,所以我不得不使用以下内容:

[module(unspecified, ...)];

这个编译很好,“未指定”选项的MSDN说:

  

禁止注入与模块属性相关的ATL代码:   注入ATL Module类,全局实例_AtlModule和入口   点函数。 ...   项目中的属性。

那么,首先,是否可以通过插件dll将exe创建到COM服务器中?其次,如果是这样,那么将“ATL模块类,全局实例_AtlModule和入口函数”添加到项目中以使其正常工作。

  • 该应用程序是标准的Windows应用程序,因此它是主要的 入口点是一个WinMain()函数。
  • 插件dll会延迟加载, 因此它不会立即加载exe。

我有点像COM业余爱好者,COM / ATL文档非常深,如此庞大而且如此广泛,我甚至不知道从哪里开始。

2 个答案:

答案 0 :(得分:2)

您可以排序执行您要求的操作(通过第三方支持为exe添加COM支持),但这会很困难,并且很多的工具都无济于事。

我正在处理ATL Internals的第2版,它解释了ATL在封面下为你做的事情。

所有COM服务器必须支持注册,必须公开类对象并管理其生命周期。

我们打得快一点在注册部分松散,因为标准方法使用一些命令行选项调用可执行文件,这显然不会为您工作。您可以让您的插件DLL在用户配置单元中自动注册CLSID(有关详细信息,请参阅this question) - 这可以避免提升问题。注册有点棘手,因为您需要为exe服务器设置注册密钥,但是从dll执行此操作。

插件加载后,您的插件将调用CoRegisterClassObject公开类对象,并在卸载插件或应用程序终止时调用CoRevokeClassObject

请注意,您需要立即调用CoRegisterClassObject""在exe开始之后。

EXE服务器的终身管理速度有点快松散 - 您可能(或可能不)关心在释放最后一个引用时卸载主机应用程序。

一旦你实现了这一点,就可以毫无困难地使用ATL的CComObject,而我相信你可以使用ATL对象图来获取CoRegisterClassObject。

答案 1 :(得分:1)

将属性扩展为C ++代码(您可以更改项目设置中的设置,并将生成的代码保存到文件中以供查看)。 [module(exe, ...会将CAtlExeModuleT作为要继承的附加基类,然后[module(dll, ...会让您CAtlDllModuleT。然而,差异不仅仅是基类,这也解释了为什么你不能轻易切换。

问题在于:归因于C ++代码曾经很酷但后来被弃用了。它仍然可以用来构建遗留项目,但是应该保持清晰。

如果项目相对较小,最好的方法是摆脱属性。这是非常可行的,因为您可以快速启动预处理器生成的扩展的非属性代码。另一方面,它可能不像听起来那么容易,因为属性有助于在不考虑过多IDL文件的情况下执行COM,如何将它们构建到项目中等。如果你能负担剥离属性,那么你想要这样做。

然后第二步是了解ATL DLL服务器和ATL EXE服务器之间的区别。最简单的方法是使用向导生成两个空项目并比较代码。您需要将相同的差异镜像到项目中,将其从DLL转换为EXE。了解这些差异,最简单的方法是使用新的ATL EXE项目并从旧的属性项目中导入相关的源代码文件。

如果您更喜欢保留属性,也许您仍然希望从空项目开始,但是我想您需要旧的Visual Studio,因为这个选项在很久以前被删除/隐藏了。要创建一个新的属性项目,我想,我想,VS 2005或2008。