所需DLL名称可变时如何在运行时选择DllImport的加载路径?
可行解决方案(极低代码侵入,兼容上游合并)
方案1:DLL导入解析器(适配.NET Core 3.0 / .NET 5 及更高版本)
该方案是当前侵入性最低的实现,原有所有[DllImport]定义和外部调用逻辑完全无需修改,仅需在程序入口处添加一次解析逻辑注册即可:
using System.Reflection; using System.Runtime.InteropServices; // 请在任何P/Invoke方法被调用前执行该注册逻辑 static void RegisterNativeLibraryResolver() { NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), (libraryName, assembly, searchPath) => { // 仅处理目标原生库的解析请求 if (libraryName != NativeLibraryName) return IntPtr.Zero; // 根据当前进程位数选择对应名称的DLL string targetLibName = Environment.Is64BitProcess ? "你的64位DLL文件名(可填完整路径)" : "你的32位DLL文件名(可填完整路径)"; return NativeLibrary.TryLoad(targetLibName, out var libHandle) ? libHandle : IntPtr.Zero; }); }
该方案支持直接指定不同名称的DLL,无需修改原有DLL的文件名或目录结构,上游代码更新时不会产生任何合并冲突。
方案2:调整系统DLL搜索顺序(适配.NET Framework 全版本)
如果你维护的是.NET Framework项目,无法使用上述原生解析器,可以使用该方案:
- 保持原有
[DllImport]中定义的库名不变,将32位版本DLL存放在程序目录下的x86子目录,64位版本DLL存放在x64子目录,两个DLL使用相同文件名。 - 在程序启动最开始执行以下逻辑:
using System.IO; using System.Runtime.InteropServices; [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool SetDllDirectory(string lpPathName); static void SetNativeLibrarySearchPath() { string archDir = Environment.Is64BitProcess ? "x64" : "x86"; string libFullDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, archDir); SetDllDirectory(libFullDir); }
该方案同样无需修改任何原有P/Invoke定义,仅需新增初始化逻辑,对原有代码的侵入性极低。
内容的提问来源于stack exchange,提问作者GameDevAlien
相关产品推荐
相关产品推荐

