C++获取dll自身模块路径的几种方法

第一种:

首先在dllmain中保存HMODULE句柄,然后使用GetModuleFileName(HMODULE) 获取,这是一个比较简单直接的方案,但是dll如果内存加载(也就是dllmain无法被正确调用的时候)就无法使用了。

第二种:

通过GetModuleHandleEx传入dll的名称获取其HMODULE,然后再通过GetModuleFileName获取路径。但是当多个装载的模块具有相同的基本名称和扩展名时,GetModuleHandleEx无法预测返回哪个模块的句柄:https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexa

HMODULE hModule = nullptr;
::GetModuleHandleEx(0, L"dllModuleName", &hModule);

第三种:

通过函数地址获取其模块句柄,然后通过GetModuleFileName传入模块句柄获取。通过地址获取模块路径又有两种方法,分别如下:

方法1

HMODULE GetSelfModuleHandle() {
  MEMORY_BASIC_INFORMATION mbi;
  if (::VirtualQuery(GetSelfModuleHandle, &mbi, sizeof(mbi)) == 0)
    return nullptr;
     
  return (HMODULE)mbi.AllocationBase;
}

方法2

HMODULE hModule = nullptr;
::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)&TestFunction, &hModule);

第四种:

通过__ImageBase获取

extern "C" IMAGE_DOS_HEADER __ImageBase;
int main() {
  wchar_t szPath[MAX_PATH] = { 0 };
  ::GetModuleFileName((HMODULE)&__ImageBase, szPath, MAX_PATH);
  return 0;
}