0

我有一个基于 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 客户端使用?

4

2 回答 2

1

在 Roman.RI 的帮助下,获得我需要的行为。我不能说谢谢,@roman-r。我将准确描述我所做的事情,所以也许有人可以追溯这些步骤并给我一些回应。

首先,我创建了一个基于 ATL 的 Windows 服务(名为 UmbrellaService)。在 UmbrellaService 中,我添加了一个名为 Control 的简单 ATL-Object 并添加了方法:

 FindMeAnInterface(BSTR moduleName, IDispatch** ppDispach);

这就是 VC++ 向导的全部内容。然后我通过添加以下内容来修复 Control.rgs 文件:

 val AppID = s '%APPID%'

为什么 VC++ 经过 17 年的演进,仍然存在这样的 bug?(请参阅 CoCreateInstance 未启动或连接到 ATL COM 服务)然后我创建了一个名为 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?还有什么我应该注意的吗?

谢谢你的帮助!

于 2012-07-10T11:18:19.573 回答
0

到目前为止我找不到我的代码。但我确实查看了我最喜欢的网站之一,The Code Project。它曾经很流行,尤其是在 COM 等较旧的技术中(是的,确实如此)。我希望您已经确信必须使用 COM 而不是新的 WFC 或其他技术。

请检查良好的文档和示例代码@ATL COM EXE doc。我相信我使用这个网页作为我过去项目的开始。

祝好运并玩得开心点。

于 2012-07-06T19:09:02.080 回答