GAC与注册表在程序集加载时是否冲突?VB脚本故障排查
我用C#项目生成了一个DLL,通过regasm注册后供多个遗留VB脚本使用。后来为了给新的C#控制台项目复用模块,把该库加入了GAC。起初一切正常,但服务器重启后VB脚本崩溃,提示无法创建库中的某类型对象。移除GAC中的库并重新用regasm注册后问题解决。
已知信息:
- 注册表和GAC中的库来自同一物理DLL,路径完全相同
- 确认
regasm执行后注册表项正常存在 - GAC项仅在安装时存在,卸载后消失,且位于
GAC_MSIL目录,符合预期
编辑补充:后来注意到regasm文档说明:
在注册表中创建Codebase项,该项指定未安装在全局程序集缓存中的程序集的文件路径。如果后续要将注册的程序集安装到全局程序集缓存中,请不要指定此选项。强烈建议与/codebase选项一起指定的assemblyFile参数为强名称程序集。
之前注册时使用了/codebase参数,正在排查,寻求更多建议。
核心原因:/codebase注册项与GAC加载优先级冲突
当你用regasm /codebase注册程序集时,注册表会生成Codebase项记录DLL本地路径。但程序集加入GAC后,.NET运行时会优先从GAC加载程序集,VB脚本作为COM客户端,在查找COM类型时会遭遇注册表Codebase路径与GAC加载逻辑的冲突——服务器重启后系统加载缓存刷新,这种冲突直接触发类型创建失败。
具体细节:
- 带
/codebase注册时,注册表记录了本地DLL路径,但程序集进入GAC后,运行时优先加载GAC版本 - COM类型的注册信息(如CLSID对应的程序集)与GAC中程序集的绑定逻辑不匹配,导致VB脚本无法正确解析类型
解决步骤
重新注册程序集(禁用
/codebase)
先移除GAC中的程序集,再执行以下命令:regasm YourAssembly.dll /unregister regasm YourAssembly.dll完成后重新将程序集加入GAC:
gacutil /i YourAssembly.dll这样注册表不会生成
Codebase项,COM客户端会自动优先从GAC加载程序集,避免路径冲突。确保程序集已强名称签名
加入GAC的程序集必须是强名称签名的,这也是regasm文档明确要求的。如果之前程序集未签名,需先完成签名再重新注册、加入GAC。验证COM注册与GAC的一致性
打开regedit,检查CLSID对应注册表项(路径示例:HKEY_CLASSES_ROOT\CLSID\{你的类型CLSID}\InprocServer32),确认Assembly值指向的是GAC中的强名称程序集,而非本地DLL路径。
内容的提问来源于stack exchange,提问作者Antidiscrete

