通过 C# 访问远程 COM 对象

Posted

技术标签:

【中文标题】通过 C# 访问远程 COM 对象【英文标题】:Accessing a remote COM object via C# 【发布时间】:2011-07-01 10:47:52 【问题描述】:

我有一个使用非托管 C++ 编写的 exe 文件,其中包含一个 COM 对象。为了从托管的 C# 应用程序访问它,我生成了一个互操作程序集。当两个应用程序在同一台 PC 上运行时,我能够非常成功地使用它。

现在,我需要让我的 C# 应用程序访问远程 PC 上的 COM 对象,而现有代码给我带来了一些问题。我不得不做一些小的改变,例如

Type ReportItemSetup = Type.GetTypeFromProgID("ACME.REPORTITEMSETUP.1", remotePCName);
RpiSetup = (IReportItemSetup)Activator.CreateInstance(ReportItemSetup);

成为

Guid gris = new Guid("147FF3D1-8A00-11F0-9A6C-0000C099D00B");
Type ReportItemSetup = Type.GetTypeFromCLSID(gris, remotePCName, true);
RpiSetup = (IReportItemSetup)Activator.CreateInstance(ReportItemSetup);

这使我能够更深入地了解代码,但后来我遇到了另一个问题。

我用:

REPORTITEMSETUPClass rpis = new REPORTITEMSETUPClass();

REPORTITEMSETUPClass 所在的位置(为简洁起见进行了编辑)

namespace Acme.ReportItemServers.Interop

    [ClassInterface(ClassInterfaceType.None)]
    [TypeLibType(TypeLibTypeFlags.FAppObject | TypeLibTypeFlags.FCanCreate | TypeLibTypeFlags.FPreDeclId)]
    [ComConversionLoss]
    [Guid("147FF3D1-8A00-11F0-9A6C-0000C099D00B")]
    public class REPORTITEMSETUPClass : IReportItemSetup, REPORTITEMSETUP, INotifySrc
    
        public REPORTITEMSETUPClass();

        ... snip ...
        public virtual void INotifySrc_AddUser(INotify pNotify, string bstrUserName);
        ... snip ...
    

我需要在 INotifySrc 接口上调用 AddUser,但 new 调用给了我错误:

Retrieving the COM class factory for component with CLSID 147FF3D1-8A00-11F0-9A6C-0000C099D00B failed due to the following error: 
80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).

这个错误是完全正确的,因为它没有在本地机器上注册。

因此,我的问题是:不能在远程 PC 上使用注册吗? Activator.CreateInstance 没有在本地注册类没有问题。

【问题讨论】:

【参考方案1】:

我认为您必须编写一个服务组件来执行此操作。这涉及到一些 COM+ 魔法并且可能相当复杂。在这里查看摘要:http://msdn.microsoft.com/en-us/library/3x7357ez%28v=vs.71%29.aspx

【讨论】:

谢谢。我会进一步研究。【参考方案2】:

创建 System.EnterpriseServices.ServicedComponent 的子类,然后在服务器的 COM+ 中安装它,然后从服务器导出一个 COM+ 代理 (msi),并在客户端安装此代理。

【讨论】:

以上是关于通过 C# 访问远程 COM 对象的主要内容,如果未能解决你的问题,请参考以下文章

如何将 C# 客户端 RPC 写入远程本机 C++ 服务器?

通过对象的名称作为字符串 c# 访问对象

如何通过索引 C# 访问对象 [关闭]

当作为 COM 对象访问时,SslStream 的响应不同

XLua 入门之 Lua 访问 C#

访问远程机器上的文件