Visual Basic COM DLL在升级版本时无法加载COM .NET程序集

3

我曾经有一个Visual Basic (VB6) COM DLL(我们称之为“dllouter”),它引用了另一个Visual Basic (VB6) COM DLL(我们称之为“dllinner”)并具有接口“Interface”。 “dllouter”以以下方式加载“dllinner”:

Public objCom As dllinner.Interface

Set objCom = New dllinner.Interface

当“dllinner”版本更改时,没有更改“Interface”,“dllouter”可以加载它而不需要重新编译它。
然后,我用带有 [assembly: ComVisible(true)] 的C#.NET程序集(VS2015)替换了“dllinner”,并重新编译了“dllouter”,一切正常工作。
但是,如果我将 [assembly: AssemblyVersion(“1.0.0”)] 更改为新版本,则 Set objCom = New dllinner.Interface 失败。我需要在更新对新“dllinner”的引用之后重新编译“dllouter”才能使其工作。
我注意到,将引用Visual Basic“dllinner”和.NET“dllinner”的.vbp文件与GUID后面列出的版本进行比较时,存在差异:
Reference = * \ G {6B0651C5-5225-42A6-841F0322797E5018}# 1.0 #0#...
粗体值针对具有新程序集版本(例如2.0)的.NET程序集进行更新,而针对Visual Basic DLL引用保持不变(无论“dllinner”版本如何始终为1.0)。
因此,我尝试在assemblyinfo.cs中添加属性 [assembly: TypeLibVersion(1,0)] ,这样做会“修复” .vbp中的引用,这意味着粗体值保持为1.0,无论AssemblyVersion是什么。 然而,问题没有解决: “dllouter”仍无法加载“dllinner”。
有没有一种方法可以解决这个问题,避免每次“dllinner”版本更改时重新编译“dllouter”?

1
你设置了CLSID和接口ID吗? - Ben
2
每个类必须有一个ComClassAttribute,该属性显式设置了接口ID(如果要创建,则还需设置CLSID):https://msdn.microsoft.com/zh-cn/library/microsoft.visualbasic.comclassattribute(v=vs.110).aspx - Ben
1
如果你不设置它们,编译器会自动生成它们,而且每个版本都会不同。为了兼容性,你需要将它们设置为与上一个版本相同的值。 - Ben
.vbp 项目在 VB6 IDE 中会保留原始的 类型库(而非 .NET 程序集),直到您将其删除并重新添加为止。类型库是带有 .tlb 扩展名的文件。 - Hans Passant
1
@Ben,我在类前面也错过了一个显式ID [Guid("C0DC113C-3839-4427-8DA5-35D768AFF3D6")] partial class classInterface : Interface {};,除了接口ID之外。现在它可以工作了。我想知道你是否想回答这个问题,还是我应该自己回答。 - BillyJoe
显示剩余4条评论
1个回答

1
如果您希望COM可见程序集与以前的版本兼容,您必须:
1)确保接口中没有可见的更改。如果已部署的接口有更改,则您的新对象不兼容,您将需要生成新的CLSIDs、IIDs和新的类型库。
2)确保每个可见类都用与上一个版本相同的IID进行了注释。如果您在上一个版本中忘记了这样做,编译器会为您生成一个,因此您需要找出它是什么,以便新版本可以相同。您可以使用TlbView或注册表来查找此信息。
3)确保每个可创建的类都用与上一个版本相同的CLSID进行了注释。
另外,检查类型库是否相同也是一个好主意。您可以使用TlbView或类似工具反编译上一个版本的类型库,然后对新版本执行相同操作。您不应该看到任何重要的差异。
注意:如果您想添加其他功能,可以这样做,但需要为新接口创建一个新的IID,该接口应继承旧接口(应标记为旧IID)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接