LoadLibrary с абсолютным путем возвращает неверный HMODULE без ошибок

У меня есть код, который пытается загрузить Dll.

Я столкнулся со странной «ошибкой» с этим. При попытке загрузить dll по абсолютному пути, я получаю ненулевой HMODULE, который не дает никаких оконных кодов ошибок при вызове GetLastError (т.е. GetLastError возвращает ‘0’ или успех в соответствии с MSDN). При вызове функции в этой DLL я получаю неправильные значения.

Это странное поведение, потому что, если вместо этого я переключаю текущий каталог на каталог моей текущей библиотеки DLL с помощью SetCurrentDirectory и использую относительный путь к 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_ * не доступны для меня (я уже пытался установить Обновление KB2533623).

2

Решение

Скорее всего проблема в том, что MyDll.dll имеет зависимости от других библиотек DLL, которые находятся в той же папке, что и MyDll.dll, Когда ваше приложение находится в другой папке, MyDll.dllэти зависимости не будут разрешены из папки, содержащей MyDll.dll, Вместо этого они разрешаются системой Порядок поиска DLL.

Ваше использование SetCurrentDirectory влияет на системный порядок поиска DLL. А это значит, что зависимости MyDll.dll разрешены из каталога, который содержит MyDll.dll,

Вы можете проверить эту гипотезу, используя, например, Dependency Walker в режиме профиля. Это скажет вам, как зависимости MyDll.dll разрешаются во время выполнения.

Вы вправе не любить использование SetCurrentDirectory, Лучшее решение — поместить все библиотеки DLL в один каталог с приложением.

Конечно, другая возможность состоит в том, что призыв к UseDLL имеет зависимость от рабочего каталога. Вы можете исключить это, изменив рабочий каталог на его первоначальное значение после вызова LoadLibrary,

6

Другие решения

Попробуйте установить SetDllDirectory или AddDllDirectory вместо SetCurrentDirectory и использовать LoadLibraryEx с флагом LOAD_LIBRARY_SEARCH_USER_DIRS вместо LoadLibrary. Полезную информацию можно найти на MSDN Вот.

Обновление: пример AddDllDirectory и связанных вызовов в Windows 7 (требуется 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;
}
5

По вопросам рекламы [email protected]