You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#获取嵌入互操作类型静态链接库路径及版本信息

解决启用嵌入互操作类型的ActiveX库路径动态获取问题

问题核心

启用嵌入互操作类型的ActiveX库,其互操作元数据会被直接嵌入到主程序集中,原库不会被独立加载,因此:

  • typeof(目标类型).Assembly.Location 返回主程序集路径,而非目标库路径
  • LoadLibrary 无法找到该库(未被显式加载到进程)

可行解决方案

1. 从注册表读取ActiveX库路径

ActiveX库注册时会在注册表中记录路径,可通过类型的CLSID查询:

  • 步骤:
    1. 获取目标类型的CLSID:Guid clsid = typeof(目标命名空间.目标类型).GUID;
    2. 根据CLSID查询对应注册表项(区分32/64位环境):
      • 32位系统/32位进程:HKEY_CLASSES_ROOT\CLSID\{CLSID}\InprocServer32
      • 64位系统下的32位进程:HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{CLSID}\InprocServer32
    3. 读取注册表项的默认值,即为库的完整路径

示例代码:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 15:15:31