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

GetModuleFileName()无法获取DLL正确路径的技术咨询

解决GetModuleFileName返回EXE路径而非当前DLL路径的问题

这问题我碰到过好多次了!核心原因很简单:当你调用GetModuleFileName(NULL, ...)时,函数默认返回的是**当前进程的主可执行文件(也就是你的EXE)**的路径,而非当前代码所在DLL的路径。这就导致你拿到的是EXE目录,自然找不到同目录下的目标DLL。

正确的解决思路

要获取当前DLL的路径,关键是要把当前DLL的模块句柄(HMODULE)传给GetModuleFileName。这里有两种可靠的实现方式:

1. 在DllMain中保存模块句柄

每个DLL被加载时,系统都会调用它的DllMain函数,并且会传入该DLL的模块句柄。你可以把这个句柄存为全局变量,后续调用GetModuleFileName时直接用它:

// 全局变量,保存当前DLL的模块句柄
HMODULE g_hCurrentDll = NULL;

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        // 保存模块句柄,后续可用
        g_hCurrentDll = hModule;
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

// 获取当前DLL所在目录的函数
std::wstring GetCurrentDllDirectory()
{
    wchar_t szFullPath[MAX_PATH] = {0};
    if (g_hCurrentDll != NULL)
    {
        GetModuleFileName(g_hCurrentDll, szFullPath, MAX_PATH);
        // 截掉文件名,只保留目录部分
        wchar_t* pLastBackslash = wcsrchr(szFullPath, L'\\');
        if (pLastBackslash != NULL)
        {
            *pLastBackslash = L'\0';
        }
    }
    return szFullPath;
}

2. 用GetModuleHandleEx反向获取模块句柄

如果不想依赖全局变量,你可以用GetModuleHandleEx,通过当前DLL中任意函数的地址来反向获取模块句柄。比如用当前函数的地址作为参数:

std::wstring GetCurrentDllDirectory()
{
    HMODULE hModule = NULL;
    // 传入当前函数的地址,获取所在模块的句柄
    GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
                      (LPCWSTR)GetCurrentDllDirectory, &hModule);

    wchar_t szFullPath[MAX_PATH] = {0};
    if (hModule != NULL)
    {
        GetModuleFileName(hModule, szFullPath, MAX_PATH);
        wchar_t* pLastBackslash = wcsrchr(szFullPath, L'\\');
        if (pLastBackslash != NULL)
        {
            *pLastBackslash = L'\0';
        }
    }
    return szFullPath;
}

加载目标DLL的完整流程

拿到DLL目录后,拼接目标DLL的路径再加载就没问题了:

// 获取当前DLL目录
std::wstring dllDir = GetCurrentDllDirectory();
// 拼接目标DLL的完整路径
std::wstring targetDllPath = dllDir + L"\\YourTargetDll.dll";
// 加载DLL
HMODULE hTargetDll = LoadLibraryW(targetDllPath.c_str());
if (hTargetDll == NULL)
{
    // 加载失败,可调用GetLastError()获取错误码排查问题
    DWORD errorCode = GetLastError();
    // 这里可以添加错误处理逻辑
}

重要提醒

  • 千万别在DllMain里直接调用LoadLibrary!这可能引发死锁或者加载顺序冲突,建议把DLL加载逻辑放到DllMain之外的初始化函数中,让EXE主动调用这个初始化函数来完成加载。
  • 如果你的DLL是延迟加载的,上面两种方法依然有效,不用担心模块句柄获取不到的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 15:32:44