windows编程之进程枚举的三种方式
2016-06-23 00:19
323 查看
在windows中,获取进程枚举有3中方式,首先是进程快照,这种方式用的较少,它涉及到了几个API,来看一下。
第一个是CreateToolhelp32Snapshot,用于获取进程相关信息的快照,声明如下:
第二个是Process32First,用于获取第一个进程的信息,声明如下:
第三个是PROCESSENTRY32结构体,保存快照信息,声明如下:
第四个是Process32Next,获取下一个进程的信息,一般与第二个函数一起使用,声明如下:
再介绍一个关于打开一个进程的函数,OpenProcess,声明如下:
下面是进程快照的测试代码:
#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,用于枚举进程,其声明如下:
第二个是GetProcessImageFileName,获取指定进程的可执行文件名,其声明如下:
一下是第二种方式的测试代码:
下面简单的介绍一下,枚举进程的第三种方式,调用NtQuerySystemInformation这个API,这个函数比较特别,因为它是ntdll.dll动态链接库里边的一个导出函数,但是以前微软并没有在MSDN上公布出来(现在好像已经公布了),但是已经有大神把它给分析出来了,现在来看一下它的声明:
其实呢,我们操作系统的任务管理器也是调用了这个API,来列举进程的,这个API可以说是我们在应用层里调用的最底层的API了,这个API还会在内核层调用一个和它相同名字的API。因此,
因为微软没有打算给我们用,所有要用到这个就比较麻烦一点,这里就不写了,如果需要的话,可以去google或者百度一下,网上都是有的,若没有找到,可以支我一声,我会及时发给你的。
第一个是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或者百度一下,网上都是有的,若没有找到,可以支我一声,我会及时发给你的。
相关文章推荐
- Android Manifest 用法
- 什么是 GraphQL?
- Spark RDD API详解(一) Map和Reduce
- 如何重装TCP/IP协议
- Spring Boot 开发微服务
- Windows 8 官方高清壁纸欣赏与下载
- 谁是桌面王者?Win PK Linux三大镇山之宝
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- Windows Clang开发环境备忘
- 从Windows系统下访问Linux分区相关软件
- 肯特·贝克:改变人生的代码整理魔法
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- Windows下搭建本地SVN服务器
- 你应该学习哪种编程语言?
- lwn拾遗:[sn3218 led drivers]-api解释-1
- 使用Windows原生命令一键清空剪贴板
- 页面元素查找之Selectors API
- windows用windeployqt发布qt quick application程序