我有一些试图加载Dll的代码。
我遇到了一个奇怪的'错误'。当尝试从绝对路径加载dll时,我得到一个非空HMODULE,它在GetLastError调用上没有提供Windows错误代码(即GetLastError根据msdn返回'0'或成功)。当调用此dll中的函数时,我得到的值不正确。
这种行为很奇怪,因为如果我使用SetCurrentDirectory将当前目录切换为当前dll的目录并使用对LoadLibrary的相对路径调用,我会得到正确的值。
以下是描述情况的摘录:
使用绝对路径:
std::string libLoc = get_dll_location(); // Get the directory of this dll
HMODULE myDLL = LoadLibraryA(libLoc.c_str()); // Non-null value
DWORD lastError = GetLastError(); // returns 0
MyObj * value = UseDLL(myDLL); // bad value
使用相对路径:
SetCurrentDirectory("c:\\path\\containing\\dll\\"); // hard coded path to dll's folder
HMODULE myDLL = LoadLibrary("myDll.dll"); // Non-null value
MyObj * value = UseDLL(myDLL); // Good value
我真的想避免使用SetCurrentDirectory,因为使用此Dll的应用程序可能是多线程的,并且要求目录保持不变。
对此问题的任何见解将不胜感激。希望这只是我的一个小错误。
更新:使用LoadLibraryEx似乎不可能,因为LOAD_LIBRARY_SEARCH_ *标记似乎对我不可用(我已经尝试安装{{ 3}})。
答案 0 :(得分:6)
问题很可能是MyDll.dll
依赖于与MyDll.dll
位于同一文件夹中的其他DLL。当您的应用程序位于与MyDll.dll
不同的文件夹中时,将无法从包含MyDll.dll
的文件夹中解析这些依赖项。相反,它们由系统DLL search order解决。
您的使用SetCurrentDirectory
会影响系统DLL搜索顺序。这意味着MyDll.dll
的依赖关系从包含MyDll.dll
的目录中解析。
您可以在配置文件模式下使用例如Dependency Walker来测试此假设。这将告诉您如何在运行时解析MyDll.dll
的依赖关系。
你不喜欢使用SetCurrentDirectory
。最好的解决方案是将所有DLL放在与应用程序相同的目录中。
当然,另一种可能性是对UseDLL
的调用依赖于工作目录。您可以通过在调用LoadLibrary
后将工作目录更改回原始值来对此进行排除。
答案 1 :(得分:5)
尝试设置SetDllDirectory或AddDllDirectory而不是SetCurrentDirectory,并使用LoadLibraryEx和标志LOAD_LIBRARY_SEARCH_USER_DIRS而不是LoadLibrary。有用的信息可以在MSDN上找到here。
更新:Windows 7上AddDllDirectory和关联调用的示例(需要KB2533623)
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
typedef DLL_DIRECTORY_COOKIE (WINAPI *ADD_DLL_PROC)(PCWSTR);
typedef BOOL (WINAPI *REMOVE_DLL_PROC)(DLL_DIRECTORY_COOKIE);
#ifndef LOAD_LIBRARY_SEARCH_USER_DIRS
#define LOAD_LIBRARY_SEARCH_USER_DIRS 0x00000400
#endif
int main()
{
ADD_DLL_PROC lpfnAdllDllDirectory = (ADD_DLL_PROC)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "AddDllDirectory");
REMOVE_DLL_PROC lpfnRemoveDllDirectory = (REMOVE_DLL_PROC)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "RemoveDllDirectory");
if(lpfnAdllDllDirectory && lpfnRemoveDllDirectory)
{
DLL_DIRECTORY_COOKIE cookie = ((ADD_DLL_PROC)lpfnAdllDllDirectory)(L"c:\\windows\\system32\\");
std::cout << cookie << std::endl;
HMODULE module = LoadLibraryEx(L"cabview.dll", NULL, LOAD_LIBRARY_SEARCH_USER_DIRS);
if(module)
{
std::cout << "Locked and loaded" << std::endl;
FreeLibrary(module);
}
if(cookie && ((REMOVE_DLL_PROC)(cookie)))
{
std::cout << "Added and removed cookie" << std::endl;
}
}
std::cin.get();
return 0;
}