WinUI 3 打包应用中DLL加载失败问题及正确加载方式咨询
遇到这种WinUI3下的DLL加载问题确实挺闹心的,毕竟同样的逻辑在控制台和WPF都能跑,偏偏WinUI3出状况——这主要是因为WinUI3的运行环境(尤其是打包模型)和传统桌面应用有不少差异,下面给你几个针对性的解决思路:
1. 先确认DLL的实际输出位置是否在进程搜索路径内
WinUI3应用(尤其是用MSIX打包的版本)的工作目录和你在解决方案里看到的输出结构可能不一样。你把DLL放到了NativeDLLs子文件夹,但默认情况下,系统的DLL搜索路径不会自动包含这个子目录。
可以先做个小测试:把DLL直接复制到和WinUI3主EXE相同的输出目录(比如bin\x64\Debug\net6.0-windows10.0.19041.0\),然后重新运行,如果能正常加载,就说明是路径问题。
2. 手动添加DLL搜索路径
如果不想把DLL放到根目录,你可以在应用启动时,手动把NativeDLLs文件夹添加到DLL搜索路径里。需要用到Windows API的AddDllDirectory方法,示例代码如下:
using System.Runtime.InteropServices; using System.IO; public static class DllLoader { [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern IntPtr AddDllDirectory(string lpPathName); public static void SetupNativeDllPath() { // 获取NativeDLLs文件夹的完整路径 string dllFolderPath = Path.Combine(AppContext.BaseDirectory, "NativeDLLs"); if (Directory.Exists(dllFolderPath)) { AddDllDirectory(dllFolderPath); } } }
然后在App.xaml.cs的OnLaunched方法开头调用DllLoader.SetupNativeDllPath(),这样后续调用interop方法时,系统就能找到子文件夹里的DLL了。
3. 调整项目中DLL的复制设置
检查你的DLL文件属性:
- 确保“生成操作”是
Content - 把“复制到输出目录”改成始终复制(而不是“较新则复制”,避免有时候因为文件时间戳问题没复制过去)
- 如果是用MSIX打包,还需要在
Package.appxmanifest里确认这些DLL被包含在打包内容中:右键项目→“编辑Package.appxmanifest”,在“打包”选项卡的“包含在包中的文件”里,添加NativeDLLs\*的规则。
4. 手动加载DLL(兜底方案)
如果上面的方法都不行,可以在调用任何interop方法之前,用LoadLibrary手动加载DLL,指定完整路径:
using System.Runtime.InteropServices; using System.IO; [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr LoadLibrary(string lpFileName); // 在应用启动时调用 var dllPath = Path.Combine(AppContext.BaseDirectory, "NativeDLLs", "openslide.dll"); LoadLibrary(dllPath);
这样CLR在后续调用interop方法时,会优先使用已经加载的DLL实例,不会再去搜索路径找。
调试小技巧
可以在代码里输出当前的工作目录和DLL的实际路径,确认文件是否存在:
using System.Diagnostics; using System.IO; Debug.WriteLine($"当前工作目录:{Directory.GetCurrentDirectory()}"); string dllPath = Path.Combine(AppContext.BaseDirectory, "NativeDLLs", "openslide.dll"); Debug.WriteLine($"DLL路径:{dllPath}"); Debug.WriteLine($"文件是否存在:{File.Exists(dllPath)}");
另外,也可以用Process Explorer工具,查看WinUI3进程加载的DLL列表,确认目标DLL是否被成功加载,或者有没有加载其他版本的DLL。
内容来源于stack exchange




