如何注册C# COM Addin使其在64位Microsoft Excel 2019中可见
解决C# COM Addin在64位Excel 2019中不可见的问题
咱们先把核心问题掰明白:32位和64位Windows的注册表是相互隔离的,64位Excel只会读取64位注册表分支,而你之前的注册代码要么没明确指定注册表视图(默认可能走32位分支),要么路径逻辑搞错了。下面给你一套能同时兼容32位和64位Excel的注册方案,一步步来解决:
关键核心点
- 64位Excel读取
HKLM\Software\Microsoft\Office\Excel\AddIns(64位注册表空间) - 32位Excel读取
HKLM\Software\Wow6432Node\Microsoft\Office\Excel\AddIns(32位注册表分支) - 不管是32还是64位,COM组件的CLSID注册都要对应到各自的注册表视图,且
InprocServer32的路径要匹配系统位数
正确的注册代码
替换你原来的注册函数,用下面的完整实现:
using Microsoft.Win32; using System; [ComRegisterFunctionAttribute] public static void RegisterFunction(Type type) { // 同时注册到64位和32位注册表,兼容两种Excel版本 RegisterInRegistry(type, RegistryView.Registry64); RegisterInRegistry(type, RegistryView.Registry32); } [ComUnregisterFunctionAttribute] public static void UnregisterFunction(Type type) { // 同时从两个注册表分支删除注册信息 UnregisterFromRegistry(type, RegistryView.Registry64); UnregisterFromRegistry(type, RegistryView.Registry32); } private static void RegisterInRegistry(Type type, RegistryView registryView) { string clsid = type.GUID.ToString("B").ToUpper(); RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registryView); // 1. 注册CLSID下的Programmable分支,这是.NET COM组件必需的 string programmablePath = $"CLSID\\{clsid}\\Programmable"; using (RegistryKey key = baseKey.CreateSubKey(programmablePath)) { // 只需创建分支,无需设置值 } // 2. 设置InprocServer32的默认值,对应位数的mscoree.dll string inprocPath = $"CLSID\\{clsid}\\InprocServer32"; string mscoreePath = registryView == RegistryView.Registry64 ? Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\mscoree.dll" : Environment.GetFolderPath(Environment.SpecialFolder.SystemX86) + @"\mscoree.dll"; using (RegistryKey key = baseKey.CreateSubKey(inprocPath)) { key.SetValue("", mscoreePath, RegistryValueKind.String); // 必须设置线程模型为Apartment,这是Excel COM Addin的硬性要求 key.SetValue("ThreadingModel", "Apartment"); } // 3. 注册到Excel AddIns分支,让Excel能识别并显示这个插件 string addinPath = $"Software\\Microsoft\\Office\\Excel\\AddIns\\{clsid}"; using (RegistryKey key = baseKey.CreateSubKey(addinPath)) { key.SetValue("FriendlyName", "我的Excel COM插件"); // 替换成你的插件名称 key.SetValue("Description", "用于测试的基础COM插件"); // 替换成你的插件描述 key.SetValue("LoadBehavior", 3); // 3=启动时自动加载,2=手动按需加载 } } private static void UnregisterFromRegistry(Type type, RegistryView registryView) { string clsid = type.GUID.ToString("B").ToUpper(); RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registryView); // 删除各分支,忽略不存在的键避免报错 try { baseKey.DeleteSubKey($"CLSID\\{clsid}\\Programmable", false); } catch { } try { baseKey.DeleteSubKeyTree($"CLSID\\{clsid}\\InprocServer32", false); } catch { } try { baseKey.DeleteSubKey($"Software\\Microsoft\\Office\\Excel\\AddIns\\{clsid}", false); } catch { } try { baseKey.DeleteSubKey($"CLSID\\{clsid}", false); } catch { } }
代码细节解释
- 注册表视图指定:通过
RegistryView.Registry64和RegistryView.Registry32分别操作两个隔离的注册表空间,确保两种Excel版本都能读到注册信息 - mscoree.dll路径:64位系统用
System文件夹下的版本,32位用SystemX86(即SysWOW64)下的版本,避免路径不匹配导致加载失败 - LoadBehavior设置:设为3让Excel启动时自动加载插件,你也可以根据需求改成2(手动加载)
- 线程模型:
Apartment是Excel COM Addin的强制要求,不设置会导致插件无法正常加载
额外注意事项
- 管理员权限:修改系统注册表需要管理员权限,不管是用VS的「注册COM互操作」功能,还是手动用
regasm.exe注册,都要以管理员身份运行 - 编译设置:你的项目是AnyCPU,确保VS项目属性→「生成」选项卡中的「注册COM互操作」是勾选状态(如果依赖VS自动注册)
- 手动注册命令:如果不用VS自动注册,64位系统下要对应使用64位的
regasm.exe,命令示例:C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe /codebase YourAddin.dll - Excel加载项检查:如果还是看不到插件,打开Excel→「文件」→「选项」→「加载项」→「COM加载项」→「转到」,看看插件是否在列表中,若存在但未勾选,手动勾选即可
按照这个方案操作,你的插件应该就能在64位Excel 2019中正常显示了!
内容的提问来源于stack exchange,提问作者Chams Souidi
相关产品推荐
相关产品推荐

