如何获取当前正在执行的代码的HMODULE?

pau*_*doo 36 c c++ winapi

我有一个静态库,可以链接到a .exe或a .dll.在运行时,我希望我的库函数可以获取HMODULE静态库代码链接到的任何内容.

我目前使用以下技巧(灵感来自此论坛):

const HMODULE GetCurrentModule()
{
    MEMORY_BASIC_INFORMATION mbi = {0};
    ::VirtualQuery( GetCurrentModule, &mbi, sizeof(mbi) );

    return reinterpret_cast<HMODULE>(mbi.AllocationBase);
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来做这个看起来不那么hacky?

(注意:这样做的目的是加载一些我知道我的用户将与我的静态库同时链接的Win32资源.)

Ser*_*ier 52

HMODULE GetCurrentModule()
{ // NB: XP+ solution!
  HMODULE hModule = NULL;
  GetModuleHandleEx(
    GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
    (LPCTSTR)GetCurrentModule,
    &hModule);

  return hModule;
}
Run Code Online (Sandbox Code Playgroud)

  • @Adrian:或者使用GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT. (15认同)
  • 请注意,如果成功,则会增加模块的引用计数,因此您需要调用"FreeLibrary". (5认同)
  • 我相信 Annon 打算建议您通过按位或将 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 与 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 结合起来,如下所示:GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT。这正是我实现调用以获取 C++ 单元测试模块的实例句柄的方法,而无需编写我自己的 DLLMain 例程。 (2认同)

MSN*_*MSN 29

__ImageBase是链接器生成的符号,它是模块的DOS头(仅限MSVC).从那里你可以将其地址转换为HINSTANCEHMODULE.所以它比通过API更方便.

所以你只需要这样做:

EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
Run Code Online (Sandbox Code Playgroud)

来自http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx

  • 错误... __ ImageBase是一个符号.如果在加载.dll或.exe时没有修复它,那么任何其他符号都不会被破坏.因此,使用它是有效的,因为它的地址在图像加载时被修复. (5认同)
  • 你怀疑陈雷蒙德?链接中的讨论表明了对链接器常量的根本误解,但最终评论是正确的。 (2认同)

Rob*_*b K 5

我会考虑GetModuleHandleEx()使用 flag GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS。看起来您可以更改GetCurrentModule()为调用此例程而不是VirtualQuery(),并将 的地址GetCurrentModule()作为lpModuleName参数传递。

预计到达时间:

const HMODULE GetCurrentModule()
{
    DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS;
    HMODULE hm = 0;
    ::GetModuleHandleEx( flags, reinterpret_cast<LPCTSTR>( GetCurrentModule ), &hm );   
    return hm;
}
Run Code Online (Sandbox Code Playgroud)

我没有尝试过,但我想这会达到你想要的效果。