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

.NET Core非当前目录启动进程时DLL加载失败问题求助

解决非可执行目录启动时的DllNotFoundException问题

这个问题的核心在于Windows的DLL搜索机制:当你不从程序exe所在目录启动时,当前工作目录(CWD)不再指向exe目录,而Windows默认会优先从当前工作目录、系统目录、PATH环境变量指定的路径查找DLL。你的C++ DLL不在这些默认搜索路径里,因此抛出了System.DllNotFoundException异常。

下面是几个针对性的解决方案,按推荐程度排序:

1. 手动添加程序集目录到DLL搜索路径(最推荐)

通过调用Windows API SetDllDirectory,把.NET Core程序集所在目录(即exe的实际存放目录)加入DLL搜索路径的最优先级位置。这样不管当前工作目录是什么,系统都会优先去这个目录查找你的C++ DLL。

实现代码示例:

using System;
using System.Runtime.InteropServices;

class Program
{
    // 导入Windows原生API
    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern bool SetDllDirectory(string lpPathName);

    static void Main(string[] args)
    {
        // 获取程序集所在的绝对目录(也就是exe的目录)
        string exeDir = AppContext.BaseDirectory;
        
        // 设置DLL搜索路径
        if (!SetDllDirectory(exeDir))
        {
            // 可选:处理设置失败的情况,比如记录日志
            int errorCode = Marshal.GetLastWin32Error();
            Console.WriteLine($"Failed to set DLL search path. Error code: {errorCode}");
        }

        // 后续调用依赖C++ DLL的方法即可正常执行
        YourDllWrapper.CallDllMethod();
    }
}

2. 用绝对路径动态加载DLL

如果不想修改全局DLL搜索路径,可以通过LoadLibrary动态加载指定绝对路径的DLL,再通过函数地址调用方法。这种方式更灵活,适合需要加载不同版本DLL的场景。

示例代码:

using System;
using System.Runtime.InteropServices;
using System.IO;

class Program
{
    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern IntPtr LoadLibrary(string lpFileName);

    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);

    // 定义与C++函数匹配的委托
    private delegate int AddNumbersDelegate(int a, int b);

    static void Main(string[] args)
    {
        // 拼接C++ DLL的绝对路径
        string dllFullPath = Path.Combine(AppContext.BaseDirectory, "YourCppDll.dll");
        IntPtr dllHandle = LoadLibrary(dllFullPath);
        
        if (dllHandle == IntPtr.Zero)
        {
            int errorCode = Marshal.GetLastWin32Error();
            throw new System.ComponentModel.Win32Exception(errorCode);
        }

        // 获取目标函数的地址
        IntPtr funcPtr = GetProcAddress(dllHandle, "AddNumbers");
        if (funcPtr == IntPtr.Zero)
        {
            int errorCode = Marshal.GetLastWin32Error();
            throw new System.ComponentModel.Win32Exception(errorCode);
        }

        // 转换为委托并调用
        AddNumbersDelegate addNumbers = Marshal.GetDelegateForFunctionPointer<AddNumbersDelegate>(funcPtr);
        int result = addNumbers(10, 20);
        Console.WriteLine($"Result: {result}");
    }
}

3. 检查C++ DLL的依赖项完整性

有时候抛出DllNotFoundException不是主DLL找不到,而是它依赖的其他组件(比如VC运行时库msvcp140.dll、vcruntime140.dll等)缺失。你可以用Dependency Walker工具扫描你的C DLL,列出所有依赖项,然后把这些依赖文件一同放到程序目录,或者在预发布环境安装对应的VC++ Redistributable包。

4. 调整PATH环境变量(不推荐)

你可以在预发布环境中将程序exe所在目录添加到系统或用户的PATH环境变量中,但这种方式灵活性差,多个版本程序共存时容易引发冲突,仅作为备选方案。


内容的提问来源于stack exchange,提问作者Xavier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:39:38