enumprocessmodules仅返回模块基地址,需配合getmodulefilenameex等函数获取路径,且必须启用sedebugprivilege权限、匹配进程架构,并处理受保护进程及unicode路径等边界情况。

Windows下用 EnumProcessModules 获取模块句柄再查路径
直接调用 EnumProcessModules 只能得到模块的基地址(HMODULE),不包含路径信息。必须配合 GetModuleFileNameEx 或 GetModuleBaseName 才能拿到完整路径或文件名。注意:该函数在 Windows 7+ 需要启用 SeDebugPrivilege 权限,否则对非本进程模块会失败并返回空字符串或错误码 ERROR_ACCESS_DENIED。
常见错误是没提权就去枚举其他进程,结果只拿到 kernel32.dll 等少数系统模块,其余全为空。调试器类工具(如 Process Hacker)都是先调用 OpenProcess + AdjustTokenPrivileges 开启调试权限,再枚举。
- 必须用
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ标志打开目标进程句柄 -
GetModuleFileNameEx在 Windows 8.1+ 推荐改用GetMappedFileName(更可靠,尤其对内存映射 DLL) - 32 位程序无法枚举 64 位进程模块(WoW64 隔离),反之亦然;需匹配架构编译
EnumProcessModulesEx 支持过滤,但依然要配 GetModuleFileNameEx
EnumProcessModulesEx 是 EnumProcessModules 的扩展版,支持传入 LIST_MODULES_ALL 或 LIST_MODULES_32BIT 等标志,能跨 WoW64 枚举部分模块,但它本身也不返回路径——只是帮你筛出更多模块句柄。路径仍得靠 GetModuleFileNameEx 逐个查。
容易忽略的是:即使开了调试权限,某些受保护进程(如 csrss.exe、smss.exe)仍拒绝提供路径,GetModuleFileNameEx 返回 0,GetLastError() 是 ERROR_PARTIAL_COPY 或 ERROR_INVALID_HANDLE,这时只能跳过。
- 传
LIST_MODULES_ALL时,返回的模块数可能大于缓冲区大小,需先调一次获取所需字节数 - 对每个
HMODULE调用GetModuleFileNameEx前,建议先用GetModuleInformation检查模块是否有效(避免访问已卸载模块) - 返回路径长度上限为
MAX_PATH(260),长路径需确保程序启用了 Unicode 和长路径支持(\?前缀无效,此 API 不识别)
替代方案:Toolhelp32Snapshot + Module32First/Next
如果只要本进程模块,或者不想处理调试权限问题,CreateToolhelp32Snapshot with TH32CS_SNAPMODULE 更轻量、无需特权。它返回 MODULEENTRY32 结构,其中 szExePath 字段直接就是完整路径。
但注意:这个快照只包含“当前时刻”加载的模块,且对远程进程效果不稳定(文档明确说明:不保证能枚举所有模块,尤其驱动级注入 DLL)。另外,MODULEENTRY32 的 szExePath 在 Windows XP 上可能为空,需 fallback 到 szModule(仅文件名)。
- 必须设置
MODULEENTRY32.dwSize = sizeof(MODULEENTRY32),否则调用失败 - 快照句柄必须用
CloseHandle释放,否则泄漏 - 不能用在 UWP 进程或某些沙箱环境(如 Edge WebView2),会返回
ERROR_ACCESS_DENIED
64 位兼容与 Unicode 路径处理
所有路径 API 默认返回宽字符(wchar_t*),必须用 GetModuleFileNameExW、Module32FirstW 等宽字符版本。混用 A 版本会导致乱码或截断,尤其路径含中文或 emoji 时。
真正容易被卡住的是:即使拿到正确路径字符串,std::wcout 在控制台默认不支持 UTF-16 输出,直接打印可能是问号或空白。临时解决可用 _setmode(_fileno(stdout), _O_U16TEXT),但生产环境更推荐转成 UTF-8 再输出或写入文件。
- 不要用
strlen测量宽字符串长度,改用wcslen -
std::wstring存储路径比std::string安全,避免编码转换丢失 - 路径中可能含重定向符号(如
C:WindowsSysWOW64kernel32.dll实际映射到System32),这是 WOW64 机制,不是 bug
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











