枚举进程:一种实用的方法






4.80/5 (17投票s)
2002年9月6日
3分钟阅读

192902
使用 ToolHelp32 库枚举进程,并展示如何更改优先级和终止进程。
引言
首先,欢迎阅读我的教程“枚举进程:一种实用方法”。在这里,我将尝试定义什么是进程,然后我们将使用 C++ 和 ToolHelp32 API 来找出我们系统中当前正在运行的进程。
什么是进程
一个进程实际上是一个正在运行的应用程序的实例。一个系统可以有同一个应用程序的多个实例,它们都在独立运行。一个进程可以启动一个子进程,这被称为子进程,而启动进程有时被称为父进程。这不像面向对象的继承,我们可以创建子类的实例而不需要创建父类的实例。在这里,父进程将首先被创建,然后是子进程,并且子进程可以与父进程共享一些资源。子进程不能脱离父进程而存在。这意味着如果父进程死亡,则子进程也会被终止。
解释
我正在使用 Visual C++ 6.0 Professional Edition,项目类型是 Win32 控制台应用程序(为了简单起见)。我们将使用来自 ToolHelp32 API 组的函数。我正在使用 Win2000,并希望它也能在 Win9x 上运行。对于 WinNT,我们使用 PSAPI (进程状态 API) 函数,这里我们不会讨论它们。
现在,首先我们将包含所有必要的头文件。
#include <windows.h> #include <tlhelp32.h> #include <iostream> #include <string> using namespace std; int main( ) { cout<<endl<<"Running Processes"<<endl;
现在,我们将使用 CreateToolhelp32Snapshot()
函数获取我们系统中当前正在运行的进程的快照,该函数返回快照的句柄,其中包含有关正在运行的进程的信息。它的原型是
HANDLE WINAPI CreateToolhelp32Snapshot( DWORD dwFlags, DWORD th32ProcessID );
在 dwFlags
中,我们将使用 TH32CS_SNAPPROCESS
和 0 作为 th32ProcessID
。有关其他选项,请参阅 MSDN。
HANDLE hSnapShot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
现在,我们已经获得了关于所有正在运行的进程的信息,在 hSnapShot
中。我们将从 hSnapShot
中提取每个进程的数据,并将其放入 PROCESSENTRY32
结构中,该结构表示一个进程,并且它是 ToolHelp32 API 的一部分。这种提取是通过使用 Process32First()
和 Process32Next()
函数完成的。在这里,我们将仅使用 Process32Next()
函数,它的原型是
BOOL WINAPI Process32Next( HANDLE hSnapshot, LPPROCESSENTRY32 lppe );
PROCESSENTRY32* processInfo=new PROCESSENTRY32;
我们必须设置 PROCESSENTRY32
结构的大小,在 dwSize
成员中。
processInfo->dwSize=sizeof(PROCESSENTRY32); int index=0;
在这里,我们将快照句柄和 PROCESSENTRY32
结构传递给 Process32Next()
函数。执行后,PROCESSENTRY32
结构将包含有关一个进程的信息。我们正在通过一个循环进行迭代,直到我们得到 FALSE
,这意味着现在没有进程可以访问快照了,并且我们的指针位于快照的末尾。
while(Process32Next(hSnapShot,processInfo)!=FALSE) { cout<<endl<<"***********************************************"; cout<<endl<<"\t\t\t"<<++index; cout<<endl<<"***********************************************"; cout<<endl<<"Parent Process ID: "<<processInfo->th32ParentProcessID; cout<<endl<<"Process ID: "<<processInfo->th32ProcessID; cout<<endl<<"Name: "<<processInfo->szExeFile; cout<<endl<<"Current Threads: "<<processInfo->cntThreads; cout<<endl<<"Current Usage: "<<processInfo->cntUsage; cout<<endl<<"Flags: "<<processInfo->dwFlags; cout<<endl<<"Size: "<<processInfo->dwSize; cout<<endl<<"Primary Class Base: "<<processInfo->pcPriClassBase; cout<<endl<<"Default Heap ID: "<<processInfo->th32DefaultHeapID; cout<<endl<<"Module ID: "<<processInfo->th32ModuleID; }
不要忘记关闭句柄。
CloseHandle(hSnapShot);
cout<<endl;
cout<<endl<<"***********************************************";
cout<<endl<<endl;
现在,我们将拥有有关正在运行的进程的所有信息,包括进程 ID(非常重要)、文件名、父进程 ID 等。我们可以通过使用 OpenProcess()
函数来获取任何正在运行的进程的句柄。
HANDLE OpenProcess( DWORD dwDesiredAccess, // access flag BOOL bInheritHandle, // handle inheritance option DWORD dwProcessId // process identifier );
有关说明,请使用 MSDN。
int processID; cout<<"Enter ProcessID to get handle of the process: "; cin>>processID;
在这里,我们正在尝试获取所有可能的访问权限。
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,TRUE,processID); if(hProcess==NULL) { cout<<"Unable to get handle of process: "<<processID; cout<<"Error is: "<<GetLastError(); return 1; }
现在我们拥有一个进程的句柄,我们可以做所有类型的神奇的事情。在这里,我们正在使用 GetPriorityClass()
函数获取进程的优先级值,然后使用 SetPriorityClass()
函数将优先级设置为高。
cout<<endl<<"Priority Class: "<<GetPriorityClass(hProcess);
SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS);
CloseHandle(hProcess);
现在,我们正在使用 TerminateProcess()
函数终止进程。
cout<<endl<<"Enter Process ID to terminate that process: "; cin>>processID; hProcess=OpenProcess(PROCESS_ALL_ACCESS,TRUE,processID); if(hProcess==NULL) { cout<<"Unable to get handle of process: "<<processID; cout<<"Error is: "<<GetLastError(); } TerminateProcess(hProcess,0);
当我们使用 new
运算符在堆上创建对象时,有必要使用 delete
显式删除它们。
delete processInfo; return 0; }
结论
在本教程中,我试图解释如何使用 C++ 获取有关正在运行的进程的信息。如果您有任何意见或问题,请给我发电子邮件。