我有一个.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中搜索我的.Net DLL版本1.0.1.3时,有三个PATH_NOT_FOUND错误(在 c:\ windows \中assembly \ GAC_32 , c:\ windows \ assembly \ GAC_MSIL 和 c:\ windows \ assembly \ GAC ) 还有一些其他错误(大多数是NAME_NOT_FOUND)但似乎在尝试了几个变化之后找到了所有这些错误。问题似乎是它正在搜索DLL的错误版本。
另一个编辑(2010-09-15,仍然):根据Hans Passant的建议,我已经在背景中执行fuslogvw运行违规代码,这些是它抛出的重要行:
日志: DisplayName = E_DataIndex,版本= 1.0.1.3,文化=中立, 公钥= c322af271028978e (完全指定的)
日志: Appbase = file:/// C:/ Archivos de programa / Microsoft Visual 工作室/ VB98 /
日志: AppName = VB6.EXE
日志:在GAC中搜索失败。
编辑:根据Hans的回答,我是早期绑定的,并且已经更改了界面的每个Guid。这似乎有效(是的,我知道,我之前应该尝试过这个)......
编辑(2010-09-17):我找到了原始问题的原因:我在注册新TLB之前没有取消注册TLB,因为我没有更改UUID的,它不断搜索安装的最新版本。 当然,我的版本控制系统并不是世界上最好的,但是知道这些陷阱我现在还会继续使用它(我对COM和.NET互操作很新)。 由于“类型不匹配”似乎是另一个无关的问题,我正在删除信息,如果我自己无法解决,我会打开一个新问题。
答案 0 :(得分:6)
COM中的版本控制是一个严重的问题。可怕的DLL Hell总是蠢蠢欲动。一个严峻的冷硬规则是,如果您更改COM组件的公共接口,那么您拥有为接口提供新的GUID。这可以确保使用以前版本的类型库编译的客户端不会意外使用新接口。
不遵循该规则会导致非常难以诊断问题。服务器的客户端将调用错误的方法。或者是正确的方法,但错误的参数。结果永远不会很好,任何事情都可能发生。如果你很幸运,那么该程序会因AccessViolation而崩溃。但是,这种运气很难获得,它通常只会以非常难以理解的方式出现故障。
根据您的问题判断,您不要在接口上使用[Guid]属性,而是将其留给编译器自动生成一个。它是通过考虑[AssemblyVersion]属性来实现的。不同的版本会自动生成不同的GUID。确实,下一步是DLL Hell避免工作,你的VB6程序再也找不到接口了。您将获得可预测的错误消息,而不是随机调用进入杂草。必须重新编译VB6程序才能使用新类型库。
请注意,这是一个非常重要的功能,而不是错误。您可以通过为接口提供[Guid]属性来自行控制它,以便它们不再依赖于程序集名称或版本。您现在必须在更改界面时手动更改它。当你忘记这样做时,迟早会付出代价。
类型库版本号同样重要。更改公共界面不简单的构建或修订更改,这是一个彻底的更改。 COM服务器的客户端要重新编译。在您的版本号中表达此信息,增加次要或主要版本号。
答案 1 :(得分:1)
这是在Windows 7 64位计算机上编译/运行吗?
转到项目属性窗口,尝试将“平台目标”从“任何CPU”切换为“x86”
尝试像CCleaner一样运行reg清理工具,并删除指向dll的所有注册表项。我有一个罕见的情况,其中两个匹配sigs的键进入注册表并手动取消注册/注册正确的组件永远不会重要,直到坏键被清理。 VS项目中的引用看起来是正确的(您可以浏览到正确的文件并添加它们而不会出现错误)但实际上指向来自错误注册表项的“ghost文件”并且每次运行/编译项目时都会死亡。 / p>