带有绝对路径的LoadLibrary返回不正确的HMODULE且没有错误

fun*_*iki 3 c++ dll winapi loadlibrary absolute-path

我有一些试图加载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
Run Code Online (Sandbox Code Playgroud)

使用相对路径:

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
Run Code Online (Sandbox Code Playgroud)

我真的想避免使用SetCurrentDirectory,因为使用这个Dll的应用程序可能是多线程的,并且要求目录保持不变.

任何关于这个问题的见解将不胜感激.希望这只是我的一个小错误.

更新:使用LoadLibraryEx似乎是不可能的,因为LOAD_LIBRARY_SEARCH_*标志似乎不可用(我已经尝试安装KB2533623更新).

Dav*_*nan 7

最有可能的问题是MyDll.dll依赖于驻留在同一文件夹中的其他DLL MyDll.dll.当您的应用程序位于不同的文件夹中时MyDll.dll,将无法从包含的文件夹中解析这些依赖项MyDll.dll.相反,它们由系统DLL搜索顺序解析.

您的使用会SetCurrentDirectory影响系统DLL搜索顺序.这意味着MyDll.dll从包含的目录解析依赖关系MyDll.dll.

您可以在配置文件模式下使用例如Dependency Walker来测试此假设.这将告诉您如何MyDll.dll在运行时解析依赖关系.

你不喜欢使用SetCurrentDirectory.最好的解决方案是将所有DLL放在与应用程序相同的目录中.

当然,另一种可能性是调用UseDLL依赖于工作目录.您可以通过在调用之后将工作目录更改回其原始值来对此进行排除LoadLibrary.


Ant*_*ill 5

尝试设置的,而不是SetCurrentDirectory SetDllDirectory会或AddDllDirectory,并使用LoadLibraryEx与标志LOAD_LIBRARY_SEARCH_USER_DIRS而不是调用LoadLibrary.有用的信息可以在MSDN上找到.

更新: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;
}
Run Code Online (Sandbox Code Playgroud)