如何从C#

时间:2019-12-21 07:28:19

标签: c# com com-interop

首先,我意识到这里有很多讨论该主题的文章。我一定很容易阅读其中的20多个。但是他们都没有给出我想要的答案。

我编写了一个小C#测试COM DLL,其中包含打印“我还活着!”的单个方法。在消息框中。使用VStudio作为管理员,我可以构建和注册COM对象。我已成功从VBA调用对象并运行该方法。我可以在“ VStudio添加引用/ COM”对话框中看到COM接口的名称。这一切使我认为该对象已正确构造,注册并可用。

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

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

另一种方法(不起作用,但我希望这样做)是通过“添加引用”对话框上的“ COM”选项卡添加引用。我可以看到它,但是VS抗议说“ XXX.tlb文件是从.NET程序集导出的。请添加对该程序集的引用。”这使我回到上面的解决方案,我认为这意味着我的应用程序在作弊。 (例如,我不必添加对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表示“此方法是为COM支持而提供的。Microsoft.NET Framework中未使用程序ID,因为它们已被名称空间的概念所取代。”因此,可能我根本不应该使用GetTypeFromProgID

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

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

有人可以给我说明或代码片段来执行“正确,已批准”的事情来从C#调用COM对象(不仅仅是我写的对象)吗?谢谢。

1 个答案:

答案 0 :(得分:1)

感谢帮助我的人们,这就是答案。 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项的引用。我想这是一个不同的问题。