so
so动态库是否加载如何判断
在Windows系统中,判断动态库(DLL)是否已加载到当前进程,可以通过以下几种方法实现:
方法1:使用 GetModuleHandle
函数
这是最直接高效的方法。该函数检查指定模块(DLL)是否已加载,若已加载则返回模块句柄,否则返回 NULL
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <Windows.h>
bool IsDllLoaded(LPCWSTR lpDllName) { HMODULE hModule = GetModuleHandleW(lpDllName); return (hModule != NULL); }
int main() { if (IsDllLoaded(L"user32.dll")) { } else { } return 0; }
|
特点:
- 不改变模块引用计数:仅查询状态,不会导致DLL被加载或卸载。
- 区分名称大小写:需确保传入的DLL名称与加载时的名称一致(通常不区分大小写,但路径需匹配)。
- 支持路径:可传入完整路径或短名称(如
L"user32.dll"
)。
方法2:遍历进程已加载模块列表
如果需要获取所有已加载模块信息(如路径、基地址),可使用以下方法:
方案A:通过 EnumProcessModules
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <Windows.h> #include <Psapi.h>
bool IsDllLoaded(LPCWSTR lpDllName) { HMODULE hModules[1024]; DWORD cbNeeded; HANDLE hProcess = GetCurrentProcess();
if (EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded)) { DWORD moduleCount = cbNeeded / sizeof(HMODULE); for (DWORD i = 0; i < moduleCount; i++) { WCHAR szModName[MAX_PATH]; if (GetModuleFileNameW(hModules[i], szModName, MAX_PATH)) { if (wcsstr(szModName, lpDllName) != NULL) { return true; } } } } return false; }
|
方案B:通过TlHelp32快照
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <Windows.h> #include <TlHelp32.h>
bool IsDllLoaded(LPCWSTR lpDllName) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); if (hSnapshot == INVALID_HANDLE_VALUE) return false;
MODULEENTRY32W me = { sizeof(me) }; if (Module32FirstW(hSnapshot, &me)) { do { if (wcscmp(me.szModule, lpDllName) == 0 || wcsstr(me.szExePath, lpDllName)) { CloseHandle(hSnapshot); return true; } } while (Module32NextW(hSnapshot, &me)); } CloseHandle(hSnapshot); return false; }
|
特点:
- 获取完整信息:可得到模块路径、基地址等。
- 开销较大:需遍历模块列表,效率低于
GetModuleHandle
。
- 适用复杂场景:如需要模糊匹配或批量检查。
关键注意事项
- 名称匹配规则:
- 若用短名称(如
"user32.dll"
),需确保与加载时一致(通常不区分大小写)。
- 若用完整路径,则需完全匹配(包括大小写和路径格式)。
- 静态链接的DLL:
- 静态链接的DLL在进程启动时自动加载,
GetModuleHandle
可直接检测。
- 动态加载的DLL:
- 通过
LoadLibrary
加载的DLL,可用上述方法检测。
- 跨进程检测:
- 若需检测其他进程,需使用
EnumProcessModules
或TlHelp32,并具有 PROCESS_QUERY_INFORMATION
权限。
总结
- 首选方案:使用
GetModuleHandle
(简单高效,适用于精确名称匹配)。
- 备选方案:遍历模块列表(需更多信息或模糊匹配时使用)。
- 避免使用:尝试
LoadLibrary
+ FreeLibrary
,这会改变引用计数且不安全。