关于C#:如何获取当前执行代码的HMODULE?

How do I get the HMODULE for the currently executing code?

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

我目前正在使用以下技巧(此论坛启发):

1
2
3
4
5
6
7
const HMODULE GetCurrentModule()
{
    MEMORY_BASIC_INFORMATION mbi = {0};
    ::VirtualQuery( GetCurrentModule, &mbi, sizeof(mbi) );

    return reinterpret_cast<HMODULE>(mbi.AllocationBase);
}

有没有更好的方法来做到这一点,看起来似乎不太hacky?

(注意:此操作的目的是加载一些Win32资源,这些资源我知道我的用户将在我的静态库的同时进行链接。)


1
2
3
4
5
6
7
8
9
10
HMODULE GetCurrentModule()
{ // NB: XP+ solution!
  HMODULE hModule = NULL;
  GetModuleHandleEx(
    GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
    (LPCTSTR)GetCurrentModule,
    &hModule);

  return hModule;
}


__ImageBase是链接器生成的符号,它是模块的DOS头(仅MSVC)。从中可以将其地址转换为HINSTANCEHMODULE。因此,它比通过API更为方便。

因此您只需要执行以下操作:

1
2
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)

来自https://devblogs.microsoft.com/oldnewthing/20041025-00/?p=37483


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

ETA:

1
2
3
4
5
6
7
const HMODULE GetCurrentModule()
{
    DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS;
    HMODULE hm = 0;
    ::GetModuleHandleEx( flags, reinterpret_cast<LPCTSTR>( GetCurrentModule ), &hm );  
    return hm;
}

我没有尝试过,但是我认为可以做您想要的。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#if _MSC_VER >= 1300  // for VC 7.0
#ifndef _delayimp_h
extern"C" IMAGE_DOS_HEADER __ImageBase;
#endif
#endif
...
HMODULE module()
{
#if _MSC_VER < 1300  // earlier than .NET compiler (VC 6.0)
    MEMORY_BASIC_INFORMATION mbi;
    static int address;
    ;::VirtualQuery(&address, &mbi, sizeof(mbi));
    return reinterpret_cast(mbi.AllocationBase);
#else  // VC 7.0
    // from ATL 7.0 sources
  return reinterpret_cast(&__ImageBase);
#endif
}

更多在这里https://www.apriorit.com/dev-blog/74-hmodule-hinstance-handle-from-static-library-in-c


HMODULE是HINSTANCE是模块的基地址。因此,我将看看它是如何工作的。但是,如果您只想要可执行文件的HMODULE,为什么不枚举进程中的所有HMODULE \\(EnumProcessModules)。其中之一将链接您的.lib。

我看到的限制是您不知道您的.lib来自哪个DLL或EXE。您可能想将HMODULE(基地址)与从.lib中获得的_ReturnAddress进行比较。您的.lib将属于小于_ReturnAddress

的最高HMODLUE