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

在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或者百度一下,网上都是有的,若没有找到,可以支我一声,我会及时发给你的。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值