进程、模块和线程枚举类






4.21/5 (9投票s)
3个简单的类,用于轻松检索正在运行的进程、模块和线程
引言
你是否曾想过 Windows 任务管理器是如何实现的?这里有 3 个类供你参考。这些类实现了对所有正在运行的进程、所有已加载的模块(可执行文件和动态链接库)以及所有线程的枚举。
这些类派生自 MFC 类 CArray
或 STL 模板类 stl::vector
。STL 实现不需要任何 MFC 组件,但支持最常用的 CArray
函数(GetSize()
、RemoveAll()
、operator[]、GetAt()
),因此可以在任何使用 CArray
的地方使用它。你可以通过在预处理器设置中定义符号 USE_STL
来启用 STL 实现。
头文件将自动指示链接器使用适当的 lib 文件。所有类都使用了 Toolhelper Library 和 psapi.lib 中的 Process Status Helper。你可以在 MSDN 上找到完整的文档。
请注意:为了使用 PSAPI,你必须安装 Platform SDK。有关使用 Toolhelp 和 PSAPI 的更多信息,请在此处 查看。
这些类远未完善,还有很大的改进空间。商业应用程序需要更深入地研究进程处理相关的安全方面,但这超出了本文的范围。
枚举进程
使用 CProcessList
类,你可以获得正在运行的进程的完整集合。该类为你提供了所有进程的所有必要信息。
// lets get a list of all processes CProcessList pl; for(int i = 0; i < pl.GetSize(); ++i) TRACE("Process %s has %i threads\n", pl[i].szModule, pl[i].pe32.cntThreads);
CProcessList
派生自 CArray<PROCESS_INFORMATION_EX, PROCESS_INFORMATION_EX>
(或 stl::vector<PROCESS_INFORMATION_EX>
)。PROCESS_INFORMATION_EX
大致定义如下:
typedef struct _PROCESS_INFORMATION_EX { ... some ctors... PROCESSENTRY32 pe32; // see tlhelp32.h PSID pSid; // contains the owning user SID TCHAR szModule[MAX_MODULE_NAME32 + 1]; // translated path+modulename } PROCESS_INFORMATION_EX;
大部分信息来自 tlhelp32.h 中定义的 PROCESSENTRY32
结构。还包括拥有该进程的用户 SID 以及包含该进程代码的模块的真实名称。
pSid
成员可以轻松用于检索用户的全名和域。
SID_NAME_USE use; DWORD dwName = 256; DWORD dwDomain = 256; TCHAR uname[256]; TCHAR udomain[256]; if(LookupAccountSid(NULL, pl[i].pSid, &uname[0], &dwName, &udomain[0], &dwDomain, &use)) { TRACE("%s\\%s", &udomain[0], &uname[0]); }
注意:对于商业应用程序,你将需要更多的代码,但对于家庭使用和演示来说,这已经足够了。
CProcessList
的析构函数负责正确释放所有分配的内存。请注意,SID 不能像结构那样复制。有关更多信息,请参阅 w32process.h 文件。
为了排除那些你没有访问权限(因为没有足够权限,例如系统进程)的进程,你可以在类的构造函数中使用可选的布尔参数。
枚举模块
由于大多数进程使用许多不同的模块,因此还有一个类用于枚举这些模块。CModuleList
也派生自集合模板类 CArray
或 vector,其中包含 tlhelp32.h 中定义的 MODULEENTRY32
结构。它基本上只是该结构的一个包装器。
当你将进程 ID 传递给构造函数时,它将枚举给定进程使用的所有已加载(!)的模块。默认构造函数枚举当前进程的模块。
请注意,模块列表在进程的生命周期内可能会发生变化,因为进程可能会动态加载和卸载 DLL。如果你想要准确的结果,必须创建一个 CModuleList
实例并立即使用它。
枚举线程
CThreadList
类是 w32process.h 中最后一个类,与其他类一样,它派生自集合模板 CArray
或 vector
。它实现了 THREAD_INFORMATION_EX
结构,该结构定义如下:
typedef struct _THREAD_INFORMATION_EX { ... some ctors... THREADENTRY32 te32; // see tlhelp32.h CONTEXT ctx; // see winnt.h } THREAD_INFORMATION_EX;
构造函数接受 2 个参数:进程 ID 和一个可选的布尔值。如果进程 ID 为 0,则枚举当前进程的线程。如果布尔参数为 true,则 ctx
成员将被填充为线程的上下文信息。这是相当特定的信息,因此默认情况下不包含。
需要注意的是,如果你需要上下文信息,该类必须暂时挂起每个线程才能获取上下文信息。
示例应用
示例应用程序展示了一个简单的进程列表,显示了基本的进程信息。当你选择一个进程时,你可以查看该进程的模块和线程。
兼容性
所有类都完全支持 MBCS/Unicode,并且可以作为 MFC CArray
派生类或 STL vector 派生类使用。在 VC7 下编写、编译和测试,但应也能在 VC6 及更早版本下编译。示例应用程序附带 STL、MFC 和 UNICODE 配置。