我目前正在编写一个加载 DLL (
a.dll
) 的程序,该程序依赖于另一个 DLL (b.dll
)。
LoadLibrary
功能时,加载a.dll
成功;只要 b.dll
与可执行文件位于同一目录中(无论 a.dll
位于何处)。但是,就我的目的而言,b.dll
不能与可执行文件位于同一目录中。因此,我求助于 LoadLibraryEx
,它有一个 flags 参数,可以在加载 DLL 时提供更具体的参数。然而,他们似乎都没有做任何事情。无论我过去几个小时尝试了什么,所有对 LoadLibraryEx
的调用都会失败并返回错误代码 126
。
HANDLE handle;
// this works if b.dll is in the same
// directory as the executable file
handle = LoadLibrary("a.dll");
FreeLibrary(handle);
// this also works, since using a value
// of zero for the flags makes it behave
// the same as LoadLibrary
handle = LoadLibraryEx("a.dll", NULL, 0);
FreeLibrary(handle);
// this does not work, even if b.dll is
// in the same directory as the executable
// file
handle = LoadLibraryEx("a.dll", NULL,
LOAD_LIBRARY_SEARCH_APPLICATION_DIR);
// this does not work, even if b.dll is
// in the same directory as a.dll
handle = LoadLibraryEx("a.dll", NULL,
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
// this does not work, even if b.dll is
// in one of the directores specified by
// a sucessful call to AddDllDirectory
DLL_DIRECTORY_COOKIE cookie =
AddDllDirectory(L"C:\\Fully\\Qualified\\Path");
handle = LoadLibraryEx("a.dll", NULL,
LOAD_LIBRARY_SEARCH_USER_DIRS);
RemoveDllDirectory(cookie);
注意:如果您需要更多信息,请在评论中告诉我,我将很乐意提供。此外,如果您选择否决这个问题,请在评论中告诉我原因。
LoadLibraryEx
定位 DLL 的方式也适用于正在加载的 DLL,而不仅仅是其依赖项(事后看来,这对我来说应该是显而易见的,但这就是编码到凌晨 1:30 的地方)。例如,如果我们有以下文件结构:
C:/
├─ Program Files/
│ ├─ My Program/
│ │ ├─ addons/
│ │ │ ├─ a.dll
│ │ ├─ depend/
│ │ │ ├─ b.dll
│ │ ├─ program.exe
并且 program.exe
运行以下命令:
DLL_DIRECTORY_COOKIE cookie =
AddDllDirectory(L"C:\\Program Files\\My Program\\depend");
HANDLE handle = LoadLibraryEx("addons\\a.dll", NULL,
LOAD_LIBRARY_SEARCH_USER_DIRS);
Windows 将尝试在 a.dll
打开
C:\\Program Files\\My Program\\depend\\addons\\a.dll
,但会失败,因为该文件不存在。在这种情况下,可以通过以下两种方法之一来解决。
// Since an absolute path is used, Windows does not need to search
// for a.dll (and thus, successfully opens it). Afterwards, it will
// search for, and successfully find, b.dll in the previously given
// depend folder.
DLL_DIRECTORY_COOKIE cookie =
AddDllDirectory(L"C:\\Program Files\\My Program\\depend");
HANDLE handle =
LoadLibraryEx("C:\\Program Files\\My Program\\addons\\a.dll",
NULL, LOAD_LIBRARY_SEARCH_USER_DIRS);
FreeLibrary(handle);
RemoveDllDirectory(cookie);
C:\\Program Files\\My Program
)。
// Here, since the program folder has also been added as a
// directory to search through, a.dll will be successfully
// found in the addons folder.
DLL_DIRECTORY_COOKIE programCookie =
AddDllDirectory(L"C:\\Program Files\\My Program\\");
DLL_DIRECTORY_COOKIE dependCookie =
AddDllDirectory(L"C:\\Program Files\\My Program\\depend");
HANDLE handle =
LoadLibraryEx("addons\\a.dll",
NULL, LOAD_LIBRARY_SEARCH_USER_DIRS);
FreeLibrary(handle);
RemoveDllDirectory(programCookie);
RemoveDllDirectory(dependCookie);
此外,确保在提供L"path"
的路径时使用宽字符串(例如,
AddDllDirectory
)!当我不使用它们时,
LoadLibraryEx
有时会在错误的文件夹中查找。例如,
C:\\Fully\\Qualified\\Path
会变成类似
C:\\Fully\\重武器家伙\\Path
的东西——至少根据 Process Monitor 是这样的。在这一点上,确保您始终对您调用的任何函数使用正确的字符串编码。
@273K 在评论中向我提及 SysInternals Process Monitor。它和 Microsoft 的Dynamic-Link Library Security 文章都有助于解决此问题。