在另一个进程中共享进程内COM对象

时间:2011-03-24 21:27:29

标签: c++ interprocess com

在我提出这个问题之前,我想明确表示我知道Inter进程通信有图书馆和技术。但这是一个关于COM的学习问题。 我也知道有关服务器外的服务器,但这不是我想要的。

问题:

我想知道的是,因为我不知道这个,是否有可能,如果是的话,如何共享一个进程中的COM对象(在DLL中定义的对象)生活在一个进程中(已经实例化了)另一个过程中的过程)?即,如何从进程B中的进程A获取指向进程内对象的指针?

提前致谢。

3 个答案:

答案 0 :(得分:8)

是的,这是可能的。无论您是在单个流程中的公寓之间还是在单独的流程之间共享单个对象实例,基本原理都是相同的。

这里有两种方法:最简单的方法是使用Running Object Table:这实际上是一个名为COM对象的工作站范围的表。您有一个进程使用一个众所周知的名称向表中添加一个对象,并让另一个进程查找该对象。

另一种方法是使用编组。封送处理是使用COM API获取描述对象位置的一系列字节的过程。然后,您可以使用任何您想要的方式(共享内存,文件,管道等)将该系列字节复制到另一个进程,然后在接收过程中使用另一个COM API来解组该对象;然后,COM在该进程中创建一个合适的远程代理,与远程代理进行通信。有关详细信息,请查看API CoMarshalIntefcaceCoUnmarshalInterface

请注意,这两者都要求您为对象提供合适的远程支持;您正在使用的接口需要在IDL中进行描述,并进行适当的编译和注册。

-

不幸的是,我没有为这两种情况提供代码。

对于CoMarshalInterface方法,该过程类似于:

  • 使用CreateStreamOnHGlobal(使用NULL hglobal)创建一个由COM根据需要分配的HGLOBAL支持的IStream
  • 使用CoMarshalInterface封送流的接口指针(然后将其写入HGLOBAL支持的内存)
  • 使用GetHGlobalFromStream从流中获取HGLOBAL
  • 使用GlobalLock / GlobalSize锁定HGLOBAL并访问已公布的数据(完成后为GlobalUnlock)
  • 使用您想要的任何方法将字节复制到目标进程。

在远端,使用:

  • GlobalAlloc / GlobalLock / GlobalUnlock创建一个新的HGLOBAL并使用封送数据填充它
  • 使用新的HGLOBAL创建CreateStreamOnHGlobal
  • 将此流传递给CoUnmarshalInterface

正常的COM和Windows引用计数/资源规则适用于所有这些; AddRef / Release视情况而定;使用GlobalFree释放您分配的任何HGLOBAL等。

答案 1 :(得分:1)

使用窗口消息WM_GETOBJECT还有另一种可能的解决方案:

在具有该对象的应用程序中,您只需使用自己的类创建一个窗口。在处理程序中,您需要像这样处理窗口消息(我使用IDispatch作为示例接口):

LRESULT WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_GETOBJECT:
        {
            if(lParam == OBJID_NATIVEOM)
            {
                return LresultFromObject(IID_IDispatch, wParam, g_MyGlobalIDispatchPointer);
            }
            else
            {
                // Not handled
                break;
            }
        }
        return 0;
    }

    // Default
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

其他应用程序必须通过AccessibleObjectFromWindow

找到特定窗口才能获取对象

例如:

HWND hWndCommunicator = FindWindow(_T("MyWindowClassOfTheOtherApplication"), _T("MyWindowTitleOfTheOtherApplication"));
if(hWndCommunicator)
{
    IDispatch* poObject = nullptr;
    HRESULT hr = AccessibleObjectFromWindow(hWndCommunicator, static_cast<DWORD>(OBJID_NATIVEOM), IID_IDispatch, &poWindow);
    if(SUCCEEDED(hr))
    {
        // Do something with the object of the other process
        // i. e. poObject->Invoke
    }
}

使用此解决方案自动完成编组。

答案 2 :(得分:0)

这就是CoRegisterClassObject和CoGetClassObject的用途。