简短的:
如何在 .NET 项目中创建两个对除了 CLSID 之外相同的非托管 COM 组件的两个引用?它们具有相同的 ProgID 和相同的类型库。
当我尝试创建第二个引用时,类型库是 Visual Studio 抱怨的:
无法添加对“XXX 类型库”的引用。已存在对此类型库的引用。在添加此之前,您必须删除引用“XXX”。
提前致谢。
详细的:
我正在创建一个 WPF 应用程序,它提供与另一个应用程序的集成。另一个应用程序有点不寻常,因为它的版本作为单独的应用程序安装。用户可以在他们的计算机上同时运行多个版本的应用程序。
我的单个 WPF 应用程序应该允许用户选择他们想要使用的其他应用程序的版本。另一个应用程序为每个安装的版本都有一个非托管 COM DLL,我用它来创建我的 WPF 应用程序和这个其他应用程序之间的集成。
我的 WPF 应用程序在使用对版本 1 的非托管 COM 组件的引用的其他应用程序的第一个版本中运行良好。当我尝试引用第二个版本的 COM 组件时,问题就开始了。
在 WPF 项目中使用“添加引用”时出现以下错误: 无法添加对“XXX 类型库”的引用。已存在对此类型库的引用。在添加此之前,您必须删除引用“XXX”。
对注册表的检查表明,两个版本的 COM 组件的注册表信息的唯一区别是 CLSD 和实际 DLL 的路径。两个组件的 ProgID 和 TypeLib 值相同。
由于其他应用程序的版本确实被视为单独的应用程序,我希望将 COM 组件安装为不同的应用程序,并且我正在与公司合作开发下一个版本。
现在我一直在尝试将第 2 版集成到我的 WPF 应用程序中。我看过很多关于 外部别名以及如何手动编辑项目文件以引入别名的帖子,但它们似乎都是从托管程序集而不是非托管 COM 组件开始的。对于引用的非托管 COM 组件,项目文件的内容是不同的,并且由于我无法创建第二个引用,因此向项目文件中的引用添加别名标记对我没有帮助。
我见过人们谈论使用 System.Addin 和反射,但我想确认在研究更复杂的方法之前没有更直接的方法。
感谢您阅读到这里!
按照 CasperOne 的建议,我做了以下事情:
- 使用 Visual Studio 命令提示符运行以下命令:tlbimp "c:\xxx1.dll" /out:"c:\NETxxx1.dll"
- 使用 Visual Studio 命令提示符运行以下命令:tlbimp "c:\xxx2.dll" /out:"c:\NETxxx2.dll"
- 添加了两个新创建的 DLL(我猜是互操作的)作为对我的测试项目的引用。我使用“浏览”选项卡来查找它们。
- 我添加了几乎遵循 casperOne 的代码示例的代码。
我对为我的 COM 接口使用什么名称感到有点恐慌。在我使用的 COM 对象的情况下,有一个主接口对象,并且我从该 COM 对象使用的所有其他对象都是从该主接口对象内实例化的(即,我进行如下调用:Foo x = y. GetNewFoo();)。
using X1 = NETXXX1;
using X2 = NETXXX2;
Guid clsid1 = new Guid("xxx...");
Type type1 = Type.GetTypeFromCLSID(clsid1);
X1.IApplication a1 = (X1.IApplication)Activator.CreateInstance(type1);
X1.FooList f1 =a1.GetFooList();
Guid clsid2 = new Guid("yyy...");
Type type2 = Type.GetTypeFromCLSID(clsid2);
X2.IApplication a2 = (X2.IApplication)Activator.CreateInstance(type2);
X2.FooList f2 = a2.GetFooList();
foreach(X1.Foo f in f1) Console.WriteLine(f.Name);
Console.WriteLine("*****");
foreach(X2.Foo f in f2) Console.WriteLine(f.Name);