.net - 文件版本与程序集版本

标签 .net com vb6 interop versioning

我有一个 .NET (FW 2.0) 库,它由 COM (vb6) 应用程序和 .NET 应用程序使用。

为COM 生成的TLB 注册的版本由“程序集版本”的前两位数字组成。例如,1.2.5.7 汇编版本成为 TLB 的 1.2 版本。这很不方便,因为有时我想更改第二个数字而不需要重新编译vb6应用程序,但似乎当TLB版本更改时我需要重新编译。

所以,我开始研究文件/程序集的事情,并尝试使用文件版本来识别我的更改,同时保持程序集版本不变。

这在 .NET 应用程序中按预期工作(即它只是工作),但在 vb6 应用程序中则不然。如果任何第三个数字不同(例如程序集版本 1.0.0.0/文件版本 1.0.2.0),每次我尝试创建新对象时都会收到“自动化错误 -2147024894 (0x80070002)”。

谁能告诉我为什么会发生这种情况,是否有任何解决方法?

编辑: 抱歉,错误代码错误。我不知道那个 438 是从哪里来的,但我发誓我在周围看到过它...

编辑(2010-09-14):奇怪的是,如果我使用程序集版本 1.0.0.0 进行编译,那么即使我重新编译 vb6 项目,我也会收到“自动化错误”。

编辑(2010-09-14,再次):在使用 ProcMon 和 FileMon 检查后,违规代码中似乎没有任何文件访问,只有注册表查询,大多数指的是其他版本的 DLL。它似乎尝试了从 1.0.0.0(具有最新代码的版本)到 1.0.1.3 的所有先前版本,但不尝试下一个版本(1.0.2.0)。文件版本现在是 1.0.2.1,如果我将程序集版本设置为 1.0.2.1,重新编译并注册它,它就可以工作。

编辑 (2010-09-15):当它在 GAC 中(在 c:\windows\assembly\GAC_32c:\windows\assembly\GAC_MSILc:\windows\assembly\GAC) 还有一些其他错误(主要是 NAME_NOT_FOUND),但似乎在尝试了几种变体之后找到了所有这些错误。问题似乎是它正在搜索错误版本的 DLL。

另一个编辑(2010-09-15,仍然):按照 Hans Passant 的建议,我在后台执行 fuslogvw 的情况下运行了有问题的代码,这些是它抛出的重要行: p>

LOG: DisplayName = E_DataIndex, Version=1.0.1.3, Culture=neutral, PublicKeyToken=c322af271028978e (Fully-specified)

LOG: Appbase = file:///C:/Archivos de programa/Microsoft Visual Studio/VB98/

LOG: AppName = VB6.EXE

LOG: Unsuccessful search in GAC.

编辑:根据Hans的回答,我是早绑定(bind)的,界面的每一个Guid都改了。这似乎可行(是的,我知道,我之前应该尝试过)...

编辑 (2010-09-17):我找到了最初问题的原因:我没有在注册新的 TLB 之前注销 TLB,因为我没有更改 UUID ,它会继续搜索安装的最新版本。 当然,我的版本控制系统不是世界上最好的,但知道这些陷阱我现在会继续使用它(我对 COM 和 .NET 互操作很陌生)。 由于“类型不匹配”似乎是另一个不相关的问题,我正在删除信息,如果我自己无法解决,我将提出一个新问题。

最佳答案

COM 中的版本控制是一件严肃的事情。可怕的 DLL hell 总是指日可待。其中一条冷酷的硬性规则是,如果您更改 COM 组件的公共(public)接口(interface),则您必须为该接口(interface)提供一个新的 GUID。这确保了使用以前版本的类型库编译的客户端不会意外使用新接口(interface)。

不遵循该规则会产生非常难以诊断的问题。服务器的客户端会调用错误的方法。或正确的方法但参数错误。结果永远不会美好,任何事情都可能发生。如果幸运的话,程序会因 AccessViolation 而崩溃。不过,这种运气很难获得,它通常会以非常难以理解的方式出现故障。

从您的问题来看,您没有在接口(interface)上使用 [Guid] 属性,而是让编译器自动生成一个。它通过考虑 [AssemblyVersion] 属性来做到这一点。不同的版本会自动生成不同的 GUID。接下来确实是 DLL Hell 回避在起作用,您的 VB6 程序再也找不到接口(interface)了。您将收到一条可预测的错误消息,而不是随机调用进入杂草。必须重新编译 VB6 程序才能使用新的类型库。

请注意,这是一个非常重要的功能,而不是错误。您可以通过为接口(interface)提供 [Guid] 属性来自行控制它,这样它们就不再依赖于程序集名称或版本。您现在必须在更改界面时手动更改它。如果您忘记这样做,迟早会付出代价。

类型库版本号同样重要。更改公共(public)接口(interface)不是简单的构建或修订更改,而是彻底的更改。 COM 服务器的客户端必须 重新编译。在您的版本号中表达这一点,增加次要或主要版本号。

关于.net - 文件版本与程序集版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3683985/

相关文章:

c# - COleDispatchDriver 错误 : automation return value coercion failed, DISP_E_TYPEMISMATCH ($80020005)

c# - SetApartmentState 和 [STAThread]

windows - 如何让旧的 VB6 应用程序在 Windows Vista 和 Windows 7 中运行?

xml - 如何加快从磁盘加载 XML 文档的速度?

c# - 将项目动态添加到上下文菜单并设置单击操作

.net - 从经典的 ASP 到 .net c# 或 vb?

C# 关于边界和行为

c# - 在 C# 中使用时间戳来测试方法长度

windows-7 - 在 Windows 7 上注册 vb6 exe 文件时出现错误(意外错误;正在退出)

vb6 - 旧版 VB6.0 应用程序中的圈复杂度