7

在我问这个问题之前,我想明确一点,我知道有用于进程间通信的库和技术。不过,这是一个关于 COM 的学习问题。我也知道进程外服务器,但这不是我想要的。

问题:

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

提前致谢。

4

3 回答 3

10

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

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

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

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

--

不幸的是,对于这两种情况,我都没有方便的代码。

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

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

在远端,使用:

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

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

于 2011-03-25T10:07:53.667 回答
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
    }
}

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

于 2016-11-11T10:36:33.573 回答
0

这就是 CoRegisterClassObject 和 CoGetClassObject 的用途。

于 2011-03-24T22:33:22.127 回答