65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (17投票s)

2002年9月6日

3分钟阅读

viewsIcon

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++ 获取有关正在运行的进程的信息。如果您有任何意见或问题,请给我发电子邮件。

© . All rights reserved.