windows编程之进程枚举的三种方式

来源:互联网 发布:3dsmax2014软件许可证 编辑:程序博客网 时间:2024/05/01 19:55

在windows中,获取进程枚举有3中方式,首先是进程快照,这种方式用的较少,它涉及到了几个API,来看一下。

第一个是CreateToolhelp32Snapshot,用于获取进程相关信息的快照,声明如下:

HANDLE WINAPI CreateToolhelp32Snapshot(    DWORD dwFlags,       //指定快照中包含的系统内容  DWORD th32ProcessID  //进程ID,为0时表示获取所有进程);

第二个是Process32First,用于获取第一个进程的信息,声明如下:

BOOL WINAPI Process32First(    HANDLE hSnapshot,        //该参为上一个函数的返回值  LPPROCESSENTRY32 lppe    //PROCESSENTRY32结构体,用于保存进程快照信息);

第三个是PROCESSENTRY32结构体,保存快照信息,声明如下:

typedef struct tagPROCESSENTRY32 {   DWORD dwSize; //结构体大小  DWORD cntUsage; //进程的引用计数,现在已经不用,为0  DWORD th32ProcessID; //进程的PID  ULONG_PTR th32DefaultHeapID;  //进程默认堆ID,现已不用,为0  DWORD th32ModuleID; //进程模块ID,现已不用,为0  DWORD cntThreads; //进程的线程计数  DWORD th32ParentProcessID; //父进程的ID  LONG  pcPriClassBase; //线程的优先级  DWORD dwFlags; //现已不用,为0  TCHAR szExeFile[MAX_PATH];    //进程的可执行文件名} PROCESSENTRY32; typedef PROCESSENTRY32 *PPROCESSENTRY32; 

第四个是Process32Next,获取下一个进程的信息,一般与第二个函数一起使用,声明如下:

BOOL WINAPI Process32Next(    HANDLE hSnapshot,  //该参数为第一个参数的返回值        LPPROCESSENTRY32 lppe  //PROCESSENTRY32结构体,用于保存进程快照信息);

再介绍一个关于打开一个进程的函数,OpenProcess,声明如下:

HANDLE OpenProcess(    DWORD dwDesiredAccess,  // 期望的访问权限  BOOL bInheritHandle,    // 是否继承父进程的句柄  DWORD dwProcessId       // 进程的PID);

下面是进程快照的测试代码:

#include <windows.h>#include <tlhelp32.h>#include <iostream>#include <stdio.h>int main(){HANDLE  hProcessSnap;HANDLE hProcess;PROCESSENTRY32 pe32;// 先去给系统的进程链表拍个照片hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);pe32.dwSize = sizeof(PROCESSENTRY32);// 获取第一个进程if (!Process32First(hProcessSnap,&pe32)){CloseHandle(hProcessSnap);return -1;}do {printf("Process name:%s PID [ %d ]\n", pe32.szExeFile, pe32.th32ProcessID);//若找到计算器进程if (lstrcmp(pe32.szExeFile, "calc.exe") == 0){//打开计算器进程,返回计算器的句柄hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);//杀掉计算器TerminateProcess(hProcess, 0);}} while (Process32Next(hProcessSnap,&pe32));return 0;}

第二种进程枚举的方法是调用EnumProcesses,这种方法用的最多,先介绍几个API。

第一个是EnumProcesses,用于枚举进程,其声明如下:

BOOL EnumProcesses(    DWORD *lpidProcess,  // 进程PID的数组  DWORD cb,            // PID数组的大小  DWORD *cbNeeded      // 数组返回的字节数);

第二个是GetProcessImageFileName,获取指定进程的可执行文件名,其声明如下:

DWORD WINAPI GetProcessImageFileName(  HANDLE hProcess,//进程句柄  LPTSTR lpImageFileName,//接收可执行文件名(全路径)的缓冲区  DWORD  nSize//缓冲区的大小);

一下是第二种方式的测试代码:

#include <stdio.h>#include <windows.h>#include <Psapi.h>#pragma comment(lib,"Psapi.lib")int main(){DWORD dwProcessID[1000];// 接收总共保存了多少字节到数组DWORD dwCBNeed;//枚举进程EnumProcesses(dwProcessID, sizeof(dwProcessID), &dwCBNeed);// 换算成进程的个数DWORD dwProcessCnt = dwCBNeed / sizeof(DWORD);//循环遍历进程,查找计算器进程for (DWORD i = 0; i < dwProcessCnt; i++){// 打开所有进程HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID[i]);//缓冲区char path[MAX_PATH];//缓冲区清0ZeroMemory(path, MAX_PATH);// 获取进程的执行文件名称GetProcessImageFileNameA(hProcess, path, MAX_PATH);printf("Process ID [ %d ] - [ %s ]\n",dwProcessID[i],path);//path = c:\\Windows\systemew\calc.exeif (strstr(path,"calc.exe")!=0){printf("已经找到计算器,正在结束...\n");//结束计算器进程TerminateProcess(hProcess, 0);}}return 0;}

下面简单的介绍一下,枚举进程的第三种方式,调用NtQuerySystemInformation这个API,这个函数比较特别,因为它是ntdll.dll动态链接库里边的一个导出函数,但是以前微软并没有在MSDN上公布出来(现在好像已经公布了),但是已经有大神把它给分析出来了,现在来看一下它的声明:

NTSTATUS WINAPI NtQuerySystemInformation(  SYSTEM_INFORMATION_CLASS SystemInformationClass,//一个系统信息类的枚举值  PVOID                    SystemInformation,//一个缓冲区,用于接收信息  ULONG                    SystemInformationLength,//缓冲区的大小  PULONG                   ReturnLength//系统返回的需要长度,一般为0);

其实呢,我们操作系统的任务管理器也是调用了这个API,来列举进程的,这个API可以说是我们在应用层里调用的最底层的API了,这个API还会在内核层调用一个和它相同名字的API。因此,

因为微软没有打算给我们用,所有要用到这个就比较麻烦一点,这里就不写了,如果需要的话,可以去google或者百度一下,网上都是有的,若没有找到,可以支我一声,我会及时发给你的。

0 0
原创粉丝点击