我有一个用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和入口函数”添加到项目中以使其正常工作。
我有点像COM业余爱好者,COM / ATL文档非常深,如此庞大而且如此广泛,我甚至不知道从哪里开始。
答案 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。