分类: C/C++
2008-08-07 17:41:35
列举加载的模块
任何时候通过 PSAPI 或 TOOLHELP32 都可以列出某个进程加载的 DLLs 列表。在写此文前的调研过程中,我研究了 Matt Pietrek 以前在
MSJ Under
The Hood 专栏中的一篇文章,其内容是讨论如何使用 TOOLHELP32 来实现前述的功能,我发现在 Windows 2000 和 Windows
XP 环境中是有问题的,代码不能正常工作,现将其代码摘录如下:
用TOOLHELP32遍历模块
// //通过取得ToolHelp32 进程快照,枚举此进程的模块列表 // HANDLE hSnapshotModule; hSnapshotModule = pfnCreateToolhelp32Snapshot( TH32CS_SNAPMODULE, procEntry.th32ProcessID ); if ( !hSnapshotModule ) continue; // 迭代快照中每一个模块 MODULEENTRY32 modEntry = { sizeof(MODULEENTRY32) }; BOOL fModWalkContinue; for (fModWalkContinue = pfnModule32First(hSnapshotModule,&modEntry); fModWalkContinue; fModWalkContinue = pfnModule32Next(hSnapshotModule,&modEntry) ) { // 确定是否为EXE文件本身,如果是,则不将它加入模块列表 if ( 0 == stricmp( modEntry.szExePath, procEntry.szExeFile ) ) continue; // 确定是否为我们已有的DLL PModuleInstance pModInst = modList.Lookup(modEntry.hModule, modEntry.szExePath ); // 如果以前没有见过,则将它加入列表 if ( !pModInst ) pModInst = modList.Add( modEntry.hModule, modEntry.szExePath ); // 将此进程加入到使用此DLL的进程列表 pModInst->AddProcessReference( procEntry.th32ProcessID ); } CloseHandle( hSnapshotModule ); // 完成模块列表快照其实并不是程序有什么瑕疵,主要是时过境迁,导致代码中一个if语句的使用无效,毕竟 Matt Pietrek 写那篇文章的时候(其代码是1998.9 在 MSJ 上发布的),Windows 2000 还不知道在哪里呢!
if ( !hSnapshotModule ) continue;实际上,如果失败,hSnapshotModule的值为INVALID_HANDLE_VALUE或-1,并且这个if语句是捕获不到它的,这到没什么,关键是如何发现这个bug。当我在Windows 2000上测试ProcessSpy时,一切运行正常,只是当列表框即便为空的时候,程序也没有返回某些进程的出错信息。由于错误处理代码本身是错的,执行跳过了循环,Module32First调用失败,但没有任何实质性的错误。如果你在Windows 2000环境用Matt Pietrek的这篇文章提供的ModuleList工具,你将得到不正确的结果。
存取器 |
说明 |
HMODULE GetModuleHandle |
DLL被映射的地址 |
CString& GetFullPathName |
源自TOOLHELP32::Module32xxx 或PSAPI::GetModuleFilenameEx |
CString& GetPathName |
同GetFullPathName |
CString& GetModuleName |
同GetFullPathName |