You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

WinUI 3 打包应用中DLL加载失败问题及正确加载方式咨询

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.csOnLaunched方法开头调用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

火山引擎 最新活动