我有一个基于ATL服务VC ++ 2010模板的进程外服务器。现在我不会通过动态加载包含其自己的COM类的其他dll来扩展其COM接口。 要加载的DLL基于ATL DLL VC ++ 2010模板,包含一个简单的ATL对象“IMModule”。我更改了相应的.rgs文件,通过添加LocalServer部分和服务器的AppID,将类从dll连接到EXE服务器,如下所示:
HKCR
{
NoRemove CLSID
{
ForceRemove {59276614-A811-4D27-B131-514656E643D3} = s 'IMModule Class'
{
ForceRemove Programmable
LocalServer32 = s 'path to the service exe'
{
val ServerExecutable = s 'path to the service exe'
}
TypeLib = s '{250685C7-CBD3-4FF8-A3A6-2AF668794CFC}'
Version = s '1.0'
val AppID = s '{7EFD508A-53C6-4EA0-B21A-D29277B86CBC}'
}
}
}
在加载dll后服务调用的dll init()方法中,我调用CoRegisterClassObject来注册IMModule类对象。但我不知道如何获取IUnknown接口指针(CoRegisterClassObject的第二个参数)。我尝试了以下方法:
CIMModule::_ClassFactoryCreatorClass* pClassFak =
new CIMModule::_ClassFactoryCreatorClass;
IUnknown* pUnk;
HRESULT hr =
pClassFak->CreateInstance(CIMModule::_ClassFactoryCreatorClass::CreateInstance,
IID_IIMModule, (LPVOID*)&pUnk);
但是对CreateInstance的调用因E_NOINTERFACE而失败。 那么,如何注册我在一个dll中实现的IMModule类,以便从我的进程外服务器可用于COM客户端?
答案 0 :(得分:1)
在Roman.R的帮助下,我得到了我需要的行为。我不能说谢谢你,@ roman-r。我会准确地描述我的所作所为,所以也许有人可以回溯这些步骤并给我一些回应。
首先,我创建了一个基于ATL的Windows服务(名为UmbrellaService)。在UmbrellaService中,我添加了一个名为Control的简单ATL对象,并添加了方法:
FindMeAnInterface(BSTR moduleName, IDispatch** ppDispach);
使用VC ++向导完成所有操作。然后我通过添加:
修复了Control.rgs文件 val AppID = s '%APPID%'
为什么VC ++在经历了17年的演变之后仍然存在这样的错误? (看到 CoCreateInstance does not start or connect to ATL COM service) 然后我创建了一个名为MyModule的ATL-dll项目,带有一个“模块” 简单的ATL-Object里面。 Module类有一个方法
testMethod (LONG a, LONG b, LONG* sum)"
MyModule dll已注册为进程内服务器。此外,DLL有一些类 这使得dll成为我需要的插件。
在UmbrellaService的PreMessageLoop方法中,MyModule dll将加载LoadLibrary,并通过GetProcAddress获取工厂创建方法的地址。工厂创建方法返回一个依赖于插件的FactoryClass,它充当插件入口点。这是我独立于COM的插件机制。
现在通过UmbrellaService接口从插件dll导出模块接口,我做了以下操作:在FactoryClass上添加方法:
IDispatch* getInterface();
在getInterface方法中,我调用
CoCreateInstance(__uuidof(Module), NULL , CLSCTX_INPROC_SERVER , __uuidof(IDispatch), (VOID**) &pDispatch);
并返回获得的IDispatch接口。在将传递给FindMeAnInterface的名称与FactoryClass提供的名称进行比较之后,在UmbrellaService的Control :: FindMeAnInterface方法内调用FactoryClass :: getInterface方法。 FindMeAnInterface将当时获得的IDispatch指针返回给客户端。
在客户端,我从UmbrellaService导入tlb文件,从适当的插件dll导入tlb。我按如下方式调用testMethod:
IControlPtr pControl(__uuidof(Control));
_bstr_t moduleName("Module");
IDispatchPtr moduleDisp = pControl->FindMeAnInterface(moduleName);
IModulePtr pModule(moduleDisp );
LONG res = pModule->testMethod(42,23);
这一切确实有效,但我不确定这是否可行。我错过了引用计数吗?插件DLL会被加载两次吗?第一次通过我的插件机制,第二次通过CoCreateInstance?还有什么我应该注意的吗?
感谢您的帮助!
答案 1 :(得分:0)
到目前为止我找不到我的代码。但我确实检查了一个我最喜欢的网站,即代码项目。它曾经很受欢迎,特别是像COM这样的旧技术(是的,它是)。我希望你已经确信你必须使用COM而不是新的WFC或其他技术。
请检查好的文档和示例代码@ ATL COM EXE doc。我相信我使用这个网页作为我过去项目的开始。
祝你好运,玩得开心。