VB6 COM DLL升级.NET COM程序集版本后无法加载的解决方法
这个问题我之前处理过好几次,核心原因是.NET COM互操作的默认行为和VB6的COM机制不一样——VB6的组件更新版本时,接口和类的GUID是固定不变的,所以引用它的VB6程序不用重新编译;但.NET默认会随着AssemblyVersion的变更,自动生成新的接口IID和类CLSID,这就导致VB6里的Set objCom = New dllinner.Interface找不到新组件,哪怕你固定了TypeLibVersion也没用,因为New操作绑定的是类的CLSID,不是类型库版本。
下面是具体的解决步骤,亲测有效:
1. 给.NET组件的接口和类显式指定固定GUID
打开你的C#项目,找到对应Interface接口和实现它的类,手动添加[Guid]特性。最好直接复用原VB6版dllinner的接口IID和类CLSID(如果能拿到的话),如果拿不到,就自己生成一组固定的GUID,之后再也不要改动。
示例代码:
// 接口的GUID,和原VB6 dllinner.Interface的IID一致最优 [Guid("6B0651C5-5225-42A6-841F-0322797E5018")] [ComVisible(true)] public interface Interface { // 你的接口方法定义 } // 实现类的GUID,和原VB6对应类的CLSID一致最优 [Guid("12345678-1234-1234-1234-123456789ABC")] [ProgId("dllinner.Interface")] // 必须和VB6代码里用的ProgID完全一致 [ComVisible(true)] public class InterfaceImpl : Interface { // 接口方法的实现代码 }
小技巧:如果不知道原VB6组件的GUID,可以用VS自带的
oleview.exe工具打开原VB6的tlb文件查看。
2. 固定类型库版本
你已经做了这一步,但再确认下AssemblyInfo.cs里的配置:
[assembly: AssemblyVersion("2.0.0.0")] // 这里可以随意更新版本号 [assembly: TypeLibVersion(1, 0)] // 固定为1.0,和VB6引用里的版本匹配 [assembly: ComVisible(true)]
这样VB6的.vbp文件里的引用版本会一直保持1.0,不会随.NET组件版本变化。
3. 正确注册.NET组件
每次更新.NET组件版本后,用regasm.exe注册时一定要加上/codebase参数(如果组件不放入GAC的话),确保注册表中写入新版本组件的正确路径:
regasm.exe YourDotNetDll.dll /tlb:YourDotNetDll.tlb /codebase
注意:必须以管理员身份运行命令提示符,否则可能出现注册权限不足的问题。
4. 验证VB6引用
打开VB6的.vbp文件,确认引用的GUID和你指定的接口GUID一致,版本号是1.0,比如:
Reference=*\G{6B0651C5-5225-42A6-841F-0322797E5018}#1.0#0#..\path\to\YourDotNetDll.tlb#YourDotNetDll Type Library
这样处理后,不管你怎么更新.NET组件的AssemblyVersion,只要接口定义不变、GUID固定,VB6的dllouter都不需要重新编译,直接就能加载新版本的.NET组件,和原来引用VB6版dllinner的行为完全一致。
内容的提问来源于stack exchange,提问作者Fabius Wiesner

