VC++ loadlibrary()加载三方dll失败, 返回错误码:126, 解决方案

本文介绍了两种在不同目录下加载DLL的方法:使用LoadLibraryEx函数并指定LOAD_WITH_ALTERED_SEARCH_PATH标志,以及通过SetCurrentDir改变当前工作目录。此外,还讨论了在64位Windows系统中如何解决32位DLL的加载问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方式一: 采用 LoadLibraryEx

若DLL不在调用方的同一目录下,可以用LoadLibrary(L"DLL绝对路径")加载。但若调用的DLL内部又调用另外一个DLL,此时调用仍会失败。解决办法是用LoadLibraryEx:
LoadLibraryEx(“DLL绝对路径”, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
通过指定LOAD_WITH_ALTERED_SEARCH_PATH,让系统DLL搜索顺序从DLL所在目录开始。

方式二: 采用 SetCurrentDir

跨目录调用dll,你应该这样

  1. 用GetCurrentDir保存当前的工作目录
  2. 用SetCurrentDir将当前的工作目录,设置为你的DLL所在的路径,需要使用绝对路径
  3. 用LoadLibrary你的DLL
  4. 使用SetCurrentDir恢复到原来的工作路径
TCHAR chCurDir[MAX_PATH] = {0};  
GetCurrentDirectory(MAX_PATH, chCurDir);  
SetCurrentDirectory(_T("E:\\test\\"));  
m_hDLL = LoadLibrary(_T("MyTest.dll"));  
SetCurrentDirectory(chCurDir);  

dll的加载顺序

  1. EXE所在目录;
  2. 当前目录GetCurrentDirectory();
  3. 系统目录GetSystemDirectory();
  4. WINDOWS目录GetWindowsDirectory();
  5. 环境变量 PATH 所包含的目录。

使用loadlibrary加载dll使用的路径时,这个函数会忽略这个路径,只会按既定规则加载dll。所以如果要加载指定目录的dll,可以用上述两个解决方案。

后续

最近又遇到一个126的问题, 采用上述两种方式依然无法解决

  • 问题描述:
    Windows 64位系统, 加载32位dll, DLL加载路径为 “C:\Windows\System32\xxx.dll”
  • 解决办法:
    将上述加载失败的DLL, 复制一份到"C:\Windows\SysWOW64"下面;
    程序不用更改, 路径参数依然填写"C:\Windows\System32\xxx.dll";
    问题解决!
  • 原因:
    简单来说可以从SysWOW64的全称找到原因:
    32bit Windows On 64bit Windows(在64位Windows上的32位Windows)
    详情可参考以下链接:
    questions from stack overflow
    什么是Wow64?
<think>好的,用户遇到了GetLastError返回126的问题,也就是加载DLL失败的错误。我需要先理解错误码126代表什么。根据微软文档,126通常意味着系统找不到指定的模块。这可能有很多原因,我需要一步步分析可能的情况。 首先,用户可能没有正确指定DLL的路径,或者路径中有拼写错误。比如,使用了相对路径但当前工作目录不对,或者文件名大小写不一致。这时候需要检查路径是否正确,尤其是绝对路径是否准确。 其次,DLL依赖的其他DLL可能缺失。比如,目标DLL可能依赖某个运行时库,如VC++ Redistributable,或者系统组件。可以用Dependency Walker工具来查看依赖关系,确认是否有未安装的依赖项。 接下来,用户可能使用的是32位和64位不兼容的DLL。如果应用程序是64位的,而DLL是32位的,或者相反,都会导致加载失败。需要确认两者的架构是否匹配。 另外,权限问题也可能导致无法加载DLL。比如,DLL所在的目录没有读取权限,或者被安全软件阻止。需要检查文件权限,以及是否有杀毒软件拦截。 还有可能是DLL文件本身损坏。这时候需要重新下载或编译DLL文件,用校验和工具确认完整性。 用户可能已经尝试过一些基本步骤,比如检查路径,但问题依然存在。可能需要更深入的排查,比如使用Process Monitor工具监视文件访问,查看系统在加载时具体访问了哪些路径,是否存在访问被拒绝的情况。 另外,用户可能在开发环境中配置错误,比如生成路径不对,导致DLL没有正确复制到输出目录。需要检查生成事件或项目设置,确保DLL被正确部署。 总结来说,我需要按照常见的错误原因,逐步引导用户检查路径、依赖、位数匹配、权限和文件完整性,并提供具体的工具和代码示例来帮助诊断问题。同时,要提醒用户使用绝对路径测试,以排除相对路径的问题,并指导他们如何获取更详细的错误信息,比如用FormatMessage格式化错误码。</think>当调用`GetLastError()`返回错误码**126**(`ERROR_MOD_NOT_FOUND`)时,表示系统在尝试加载DLL时未能找到目标文件或其依赖项。以下是针对此问题的详细分析和解决方案: --- ### **1. 错误码126的常见原因** - **DLL路径错误**:路径不存在、文件名拼写错误、路径权限不足。 - **依赖链断裂**:目标DLL依赖的其他DLL缺失或损坏。 - **32/64位不兼容**:进程与DLL的架构(x86/x64)不匹配。 - **安全软件拦截**:杀毒软件或系统策略阻止DLL加载。 --- ### **2. 逐步排查与解决方案** #### **步骤1:验证DLL路径** - **检查路径是否存在** 使用绝对路径直接测试(避免相对路径歧义): ```cpp HMODULE hDll = LoadLibrary(L"C:\\MyApp\\Bin\\MyLibrary.dll"); if (hDll == NULL) { DWORD err = GetLastError(); // 若失败,err=126 } ``` **注意**: - 路径中的反斜杠需转义(`\\`)或使用原始字符串(`LR"(C:\MyApp\Bin\MyLibrary.dll)"`)。 - 检查文件名大小写(Linux子系统或跨平台编译时需注意)。 - **获取系统搜索路径** 系统按以下顺序搜索DLL: 1. 应用程序所在目录 2. 系统目录(`C:\Windows\System32`) 3. 当前工作目录(可能与exe路径不同!) 4. `PATH`环境变量中的目录 使用`GetCurrentDirectory`确认当前工作目录: ```cpp wchar_t buffer[MAX_PATH]; GetCurrentDirectory(MAX_PATH, buffer); wprintf(L"Current Directory: %s\n", buffer); ``` --- #### **步骤2:检查DLL依赖项** - **使用工具分析依赖** 通过以下工具检查目标DLL的依赖链: - **Dependency Walker**(Depends.exe):经典工具,但可能不兼容新版DLL。 - **Visual Studio的Dumpbin**: ```bash dumpbin /DEPENDENTS MyLibrary.dll ``` - **Process Monitor**(ProcMon):实时监控DLL加载过程,记录缺失文件。 - **修复依赖项缺失** 若依赖的DLL(如`VCRUNTIME140.dll`)缺失: - 安装对应版本的[Visual C++ Redistributable](https://aka.ms/vs/17/release/vc_redist.x64.exe)。 - 将依赖DLL复制到应用程序目录或系统搜索路径。 --- #### **步骤3:确认架构一致性** - **检查进程与DLL的位数** - **任务管理器**:查看进程的“平台”列(x86或x64)。 - **DLL文件属性**:在资源管理器中右键DLL → “属性” → “详细信息” → “机器类型”。 - **强制指定加载器行为**(仅限调试): 使用`LoadLibraryEx`并指定`LOAD_LIBRARY_AS_IMAGE_RESOURCE`绕过部分验证(不推荐生产环境)。 --- #### **步骤4:排除权限与文件锁** - **检查文件权限** 右键DLL → “属性” → “安全” → 确保当前用户有**读取**权限。 - **解除文件占用** 使用[Process Explorer](https://learn.microsoft.com/zh-cn/sysinternals/downloads/process-explorer)搜索DLL句柄,结束占用进程。 --- #### **步骤5:验证DLL完整性** - **重新编译或替换DLL** 若DLL为自行编译: - 检查编译配置(Debug/Release、静态链接/动态链接)。 - 确认导出函数符号(`__declspec(dllexport)`)。 - **校验文件哈希** 使用`certutil`命令验证文件是否损坏: ```bash certutil -hashfile MyLibrary.dll SHA256 ``` --- ### **3. 代码示例:增强错误诊断** ```cpp #include <windows.h> #include <iostream> #include <format> void LoadDllWithDiagnostics(const wchar_t* dllPath) { HMODULE hDll = LoadLibrary(dllPath); if (hDll == NULL) { DWORD err = GetLastError(); LPWSTR errMsg = nullptr; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, 0, (LPWSTR)&errMsg, 0, nullptr ); std::wcerr << L"加载DLL失败: " << dllPath << L"\n" << L"错误码: " << err << L"\n" << L"错误信息: " << errMsg << std::endl; LocalFree(errMsg); } else { std::wcout << L"DLL加载成功!" << std::endl; FreeLibrary(hDll); } } int main() { LoadDllWithDiagnostics(L"MyLibrary.dll"); return 0; } ``` --- ### **4. 高级排查工具** | 工具 | 用途 | |--------------------|---------------------------------------| | **Process Monitor** | 监控文件访问、注册表操作、进程加载事件 | | **Windbg** | 分析加载器错误(`!loaddll`命令) | | **Sigcheck** | 检查DLL签名和版本信息 | --- 通过以上步骤,可系统性定位并解决DLL加载失败问题。若仍无法解决,建议提供完整的错误日志、DLL依赖树及环境信息以进一步分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值