使用 COM 在 Windows 上的本地计算机上进行进程间通信

Posted

技术标签:

【中文标题】使用 COM 在 Windows 上的本地计算机上进行进程间通信【英文标题】:Interprocess communication on local machine on Windows using COM 【发布时间】:2015-01-19 12:05:12 【问题描述】:

我正在研究在 Windows 上使用 COM 和 C++ 进行进程间通信的选项

我找到了this article on MSDN,它提供了 Windows 的进程间通信选项列表,COM 就是其中之一。 但是,不幸的是,COM 选项只是列出,没有太多细节。

有人对如何在 Windows 上使用 COM 进行进程间通信的文档或其他资源有任何指示吗?

我对与远程机器通信不感兴趣(所以:没有 DCOM);我只是对同一台本地机器上的进程间通信感兴趣。

想法是定义一些自定义的COM接口,实现一些自定义的通信协议,然后有一个服务器程序和一个客户端程序(各自在自己的进程中,运行在同一台本地机器上),并使用COM进行通信两者之间(例如,客户端向服务器发出请求,服务器返回正确的答案,一切都使用 COM 接口)。

那么,例如:是否有预定义的 COM 接口来实现进程间通信?如果有,它们是什么?

如果有一些关于这个主题的教程或更详细的指南会很有帮助。

【问题讨论】:

支持进程互操作是COM中的一种天生能力,它不需要“特殊”接口。我们在这里不做教程链接,但你已经知道了。 我了解 in-proc COM DLL(例如 shell 扩展),但我从未做过进程外 COM 服务器,也从未做过使用 COM 作为进程间通信的一种形式。 @patthoyts 的回答至少是提及此 "Running Object Table" 元素的初步指导。 COM 很大,有一些指向重点文档和教程的指针真的很有帮助。 【参考方案1】:

如果你有一个双方都知道的 COM 接口,那么一个进程可以使用名字对象注册一些实现该接口的对象,Running Object Table。然后,其他进程可以使用名字对象标识符从这个进程间表中检索对象,并查询已知接口。现在客户端进程引用了其他进程中存在的内容,并且调用将由 COM 编组。

虽然有很多事情会出错,尤其是在确保您的接口被正确编组方面。直到您开始使用多个进程或者您一直在将 .Net 与您的 COM 接口一起使用之前,编组通常都没有经过很好的测试。使用oleautomation 兼容类型并在IDL 中使用[oleautomation] 属性标记接口有助于确保类型库编组能够正常工作,但注意与数组一起使用的其他属性也很重要。几年前,我们通过IPropertyBag2 界面发现了这一点。 Visual Studio 6 IDL 描述在 ocidl.idl 中如下所示:

HRESULT Read(
            [in] ULONG cProperties,
            [in] PROPBAG2 * pPropBag,
            [in] IErrorLog * pErrLog,
            [out] VARIANT * pvarValue,
            [out] HRESULT * phrError
        );

并且不会从提供的数组中编组多个 VARIANT。较新的版本如下所示:

HRESULT Read(
           [in] ULONG cProperties,
           [in, size_is(cProperties)] PROPBAG2 * pPropBag,
           [in, unique] IErrorLog * pErrLog,
           [out, size_is(cProperties)] VARIANT * pvarValue,
           [in, out, unique, size_is(cProperties)] HRESULT * phrError
       );

正确地将pvarValue 数组的大小与cProperties 参数指定的大小相关联。假设已经注册了具有第二个定义的类型库,那么这个接口现在应该可以正确编组,但几年前那些缺失的参数让我们花费了一些脑细胞来弄清楚持久性失败的原因。

【讨论】:

感谢这些指向运行对象表的指针和其他一般信息。您能否详细说明一下接口编组出错的情况?我的意思是:当然我不会在接口边界有像std::vector 这样的STL 类,但是如果我将编组接口的类型限制为“简单”类型,如整数、布尔值和COM 类型,如BSTR,我会安全吗?和其他接口指针(例如IUnknown*)? 我对过去遇到的一些编组陷阱进行了扩展。 感谢您的补充。 让我警告你,第二个定义在类型库方面毫无价值,因为它们没有描述数组参数的长度。对于自动化数组,您必须使用SAFEARRAYVARIANT 指向一个。如果您使用 midl.exe 生成代理存根代码以包含在 DLL(组件的 DLL 或单独的 DLL)中并在HKEY_CLASSES_ROOT\Interface 中注册接口,则第二个定义将起作用。 确实,使用 oleview 检查 IPropertyBag2 接口使用了 oleaut32 提供的自定义类,并且没有使用类型库编组。

以上是关于使用 COM 在 Windows 上的本地计算机上进行进程间通信的主要内容,如果未能解决你的问题,请参考以下文章

windows 无法在本地计算机上启动服务错误 5 访问被拒绝

本地计算机上的 Windows 服务启动然后停止错误

Windows 无法在本地计算机上启动 Apache2 - 问题

Windows 无法在本地计算机上启动 SQL Server (SQLEXPRESS) 服务。错误 1053

在本地系统下运行的 Windows 服务可以在运行它的计算机上创建新文件吗?

以编程方式在远程计算机上安装 Windows 服务