4

Dll をロードしようとしているコードがいくつかあります。

これで奇妙な「エラー」が発生しました。絶対パスから dll をロードしようとすると、GetLastError 呼び出しで Windows エラー コードを返さない Non-Null HMODULE を取得します (つまり、 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

この Dll を使用するアプリケーションはマルチスレッドであり、ディレクトリが同じままである必要があるため、SetCurrentDirectory を使用する必要はありません。

この問題に関する洞察をいただければ幸いです。うまくいけば、これは私の側の小さなバグです。

更新: LOAD_LIBRARY_SEARCH_* フラグが使用できないように見えるため、 LoadLibraryExを使用することは問題外のようです (私は既にKB2533623 更新プログラムをインストールしようとしました)。

4

2 に答える 2

7

最も可能性の高い問題はMyDll.dllMyDll.dll. アプリケーションが とは別のフォルダにある場合MyDll.dll、それらの依存関係は を含むフォルダから解決されませんMyDll.dll代わりに、システムDLL 検索順序によって解決されます。

ユーザーの使用SetCurrentDirectoryは、システム DLL の検索順序に影響します。そして、 の依存関係がMyDll.dllを含むディレクトリから解決されることを意味しますMyDll.dll

たとえば、プロファイル モードで Dependency Walker を使用して、この仮説をテストできます。これにより、実行時に の依存関係がどのようにMyDll.dll解決されるかがわかります。

の使用を嫌うのは当然ですSetCurrentDirectory。最善の解決策は、すべての DLL をアプリケーションと同じディレクトリに置くことです。

もちろん、別の可能性として、への呼び出しがUseDLL作業ディレクトリに依存している可能性があります。の呼び出し後に作業ディレクトリを元の値に戻すことで、これを除外できますLoadLibrary

于 2012-11-06T17:23:17.417 に答える
5

SetCurrentDirectoryの代わりにSetDllDirectoryまたはAddDllDirectoryを設定し、LoadLibraryの代わりにフラグLOAD_LIBRARY_SEARCH_USER_DIRSを指定してLoadLibraryExを使用してみてください。有用な情報は、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;
}
于 2012-11-06T17:34:09.073 に答える