You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2.7 KiB
2.7 KiB
| title | date | tags | categories |
|---|---|---|---|
| 动态获取当前模块的HMODULE/HINSTANCE值 | 2018-05-14 18:38:45 | [win32] | windows |
如何动态获取当前代码运行时所在的模块句柄?这里介绍三种方法。
1. 使用GetModuleHandle
这是标准方案,可以动态获取exe或者dll模块句柄。
HMODULE WINAPI GetModuleHandle(
_In_opt_ LPCTSTR lpModuleName
);
其中lpModuleName为dll或者exe名,如果扩展名被省略,默认会追加.dll后缀。如果结尾为.,则表示模块没有后缀名。一般来说,只需要执行模块名就可以了,如果指定了完整路径,分隔符必须使用\,不能使用/,如果使用NULL,则返回创建当前进程的exe句柄。另外,如果dll文件是以资源文件形式被加载,即指定了LOAD_LIBRARY_AS_DATAFILE,是无法使用该函数获取到句柄的。
2. 使用VirtualQuery
函数原型为
SIZE_T WINAPI VirtualQuery(
_In_opt_ LPCVOID lpAddress,
_Out_ PMEMORY_BASIC_INFORMATION lpBuffer,
_In_ SIZE_T dwLength
);
其中,MEMORY_BASIC_INFORMATION 结构体中的AllocationBase 就是模块基址,可以转换成模块句柄。
typedef struct _MEMORY_BASIC_INFORMATION {
PVOID BaseAddress;
PVOID AllocationBase;
DWORD AllocationProtect;
SIZE_T RegionSize;
DWORD State;
DWORD Protect;
DWORD Type;
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
3. 使用伪变量__ImageBase
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
如果使用Microsoft链接器,就可以使用上面的方法来获取当前代码所在模块的句柄。伪变量__ImageBase 表示模块的DOS头,即这个模块的起始地址。
一般使用场景为,编写了一个静态库,提供给其他人调用,需要动态获取运行时所在模块的句柄。
#if _MSC_VER >= 1300 // for VC 7.0
// from ATL 7.0 sources
extern "C" IMAGE_DOS_HEADER __ImageBase;
#endif
HMODULE GetCurrentModule()
{
#if _MSC_VER < 1300 // earlier than .NET compiler (VC 6.0)
// Here's a trick that will get you the handle of the module
// you're running in without any a-priori knowledge:
// http://www.dotnet247.com/247reference/msgs/13/65259.aspx
MEMORY_BASIC_INFORMATION mbi;
static int dummy;
VirtualQuery(&dummy, &mbi, sizeof(mbi));
return reinterpret_cast<HMODULE>(mbi.AllocationBase);
#else // VC 7.0
// from ATL 7.0 sources
return reinterpret_cast<HMODULE>(&__ImageBase);
#endif
}
参考链接: