如何从 C# 调用 COM 对象

How to call a COM object from C#

首先,我发现这里有很多帖子讨论这个话题。我一定已经轻松阅读了其中的 20 多本。但其中 none 给出了我寻求的答案。

我编写了一个小型 C# 测试 COM DLL,其中只有一个方法可以在消息框中打印 "I am alive!"。使用 VStudio 作为管理员,我可以构建和注册 COM 对象。我已经从 VBA 和 运行 方法中成功调用了对象。我可以在 VStudio 添加引用/COM 对话框中看到 COM 接口的名称。这一切让我觉得该对象已正确构建、注册和可用。

现在我正尝试从控制台 C# 应用程序调用它。像许多其他人一样,我试图找出与 VBA "CreateObject("DLLName.ClassName")" 代码等效的代码来获取 C# 中的对象。

一种方法是将对 DLL 的引用添加到我的控制台应用程序项目中。我通过“添加引用”对话框的“项目”部分指向程序集,而不是通过对话框的 COM 部分。然后我可以简单地说 var o = new MyComImplementationClass(); 并像对待任何其他 class 一样对待它。这行得通,但这意味着我的控制台应用程序作弊并且没有通过通常的 COM GAC 界面使用 COM 对象。

另一种方法(行不通,但我希望如此)是通过“添加引用”对话框中的 COM 选项卡添加引用。我可以看到它,但 VS 抗议 "the XXX.tlb file was exported from a .NET assembly. Add a reference to the assembly instead." 这让我回到上面的解决方案,我认为这意味着我的应用程序在作弊。 (例如,我不必添加对我的 VBA 测试应用程序的引用。)

另一种方法是使用 Type.GetTypeFromProgId,如下面的代码片段所示。但我也无法让它发挥作用。我一定是传递了不正确的 ProgID 字符串 - 我感觉它与注册表信息有关,并且与我在 VBA 中输入 CreateObject() 的 "DLLName.ClassName" 字符串不同。

  public static dynamic ComObjectGet () {
    const string progID = "ComExampleDLLName.ComImplementationClassName";
    Type foo = Type.GetTypeFromProgID (progID);
    dynamic COMobject = Activator.CreateInstance (foo);
    return COMobject;
  }

更糟糕的是,on this MSDN example page 它说 "This method is provided for COM support. Program IDs are not used in Microsoft .NET Framework because they have been superseded by the concept of namespace." 所以我可能根本不应该使用 GetTypeFromProgID

如果有帮助,我可以在 C# 中使用 VSTO 来调用 MSOffice 主互操作程序集。但它们是从添加引用对话框的 COM 选项卡加载的(这是我希望我的 COM 库从中加载的位置)。

为清楚起见,我的 COM DLL 名称是 ComExampleLibrary.dll。默认命名空间是 ComExampleNamespace。接口名称是 IComInterface,实现 classname 是 ComImplementation。内部方法名称是 运行.

有人可以给我说明或代码片段来执行 "right, approved" 从 C# 调用 COM 对象(不仅仅是我编写的对象)的事情吗?谢谢。

感谢帮助我的人,这里是答案。 GetTypeFromProgIDGetTypeFromCLSID 的工作方式如下所示。我的问题是我在调用 GetTypeFromProgID 时使用 "AssemblyName.ClassName" 而不是 "Namespace.ClassName"。

 public static dynamic ComObjectGet () {
    const string progID = "ComExampleNamespace.ComImplementation";
    Type foo = Type.GetTypeFromProgID (progID);

    //var bar = Guid.Parse ("99929AA7-0334-4B2D-AC74-5E282A12D06C");
    //Type foo = Type.GetTypeFromCLSID (bar);

    dynamic COMobject = Activator.CreateInstance (foo);
    return COMobject;
  }

所以我的原始代码是正确的,但我传递了错误的参数。此代码段相当于 VBA CreateObject("Namespace.ClassName") 调用。

我仍然不知道为什么我不能在添加引用对话框的 COM 选项卡中添加对 COM 项的引用,就像我对任何其他 COM 对象所做的那样。我想这是一个不同的问题。