您的位置:首页 > 编程语言

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

2016-06-23 00:19 323 查看
在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];
//缓冲区清0
ZeroMemory(path, MAX_PATH);
// 获取进程的执行文件名称
GetProcessImageFileNameA(hProcess, path, MAX_PATH);
printf("Process ID [ %d ] - [ %s ]\n",dwProcessID[i],path);
//path = c:\\Windows\systemew\calc.exe
if (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或者百度一下,网上都是有的,若没有找到,可以支我一声,我会及时发给你的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息