C#获取嵌入互操作类型静态链接库路径及版本信息
解决启用嵌入互操作类型的ActiveX库路径动态获取问题
问题核心
启用嵌入互操作类型的ActiveX库,其互操作元数据会被直接嵌入到主程序集中,原库不会被独立加载,因此:
typeof(目标类型).Assembly.Location返回主程序集路径,而非目标库路径LoadLibrary无法找到该库(未被显式加载到进程)
可行解决方案
1. 从注册表读取ActiveX库路径
ActiveX库注册时会在注册表中记录路径,可通过类型的CLSID查询:
- 步骤:
- 获取目标类型的CLSID:
Guid clsid = typeof(目标命名空间.目标类型).GUID; - 根据CLSID查询对应注册表项(区分32/64位环境):
- 32位系统/32位进程:
HKEY_CLASSES_ROOT\CLSID\{CLSID}\InprocServer32 - 64位系统下的32位进程:
HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{CLSID}\InprocServer32
- 32位系统/32位进程:
- 读取注册表项的默认值,即为库的完整路径
- 获取目标类型的CLSID:
示例代码:
using Microsoft.Win32; using System; public static string GetActiveXLibraryPath(Type comType) { Guid clsid = comType.GUID; string registryPath = $"CLSID\\{clsid.ToString("B")}\\InprocServer32"; // 适配64位系统下的32位进程 if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess) { registryPath = $"Wow6432Node\\{registryPath}"; } using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(registryPath)) { return key?.GetValue(null) as string; } } // 调用示例 string libraryPath = GetActiveXLibraryPath(typeof(目标命名空间.目标接口或类)); if (!string.IsNullOrEmpty(libraryPath)) { FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(libraryPath); // 后续版本信息处理逻辑 }
2. 触发库加载后通过Kernel32获取路径
先创建ActiveX类型的实例(触发库加载到进程),再用GetModuleHandleEx + GetModuleFileName获取路径:
- 注意:需确保实例创建成功,库已被加载
示例代码:
using System; using System.Runtime.InteropServices; public static string GetLoadedLibraryPath(Type comType) { // 创建实例触发库加载 object instance = Activator.CreateInstance(comType); if (instance == null) return null; // 获取实例方法的内存地址,用于定位模块 var method = comType.GetMethod("目标方法名"); if (method == null) return null; IntPtr methodPtr = Marshal.GetMethodPointerForDelegate(method.CreateDelegate(typeof(Action), instance)); IntPtr moduleHandle = IntPtr.Zero; GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, methodPtr, ref moduleHandle); if (moduleHandle != IntPtr.Zero) { char[] pathBuffer = new char[256]; GetModuleFileName(moduleHandle, pathBuffer, (uint)pathBuffer.Length); return new string(pathBuffer).TrimEnd('\0'); } return null; } // Kernel32 API声明 [DllImport("kernel32.dll", SetLastError = true)] private static extern bool GetModuleHandleEx(uint dwFlags, IntPtr lpModuleName, ref IntPtr phModule); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern uint GetModuleFileName(IntPtr hModule, char[] lpFilename, uint nSize); private const uint GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 0x00000004;
注意事项
- 注册表方法依赖ActiveX库已正确注册,未注册则无法使用
- 若库为延迟加载,需确保已触发加载后再调用
GetModuleHandleEx - 需注意32/64位进程与系统的兼容性问题
内容的提问来源于stack exchange,提问作者DrDoom
相关产品推荐
相关产品推荐

