假设某天我突发奇想,想要实现:
输入一个进程名字,输出该进程的句柄、内存占用、CPU使用情况。
ok,那我们来看下如何扯出这个程序,以下演示程序基于vs2008,更高版本可能会有字符问题。
1)在系统中查找是否存在指定进程名的进程:
这里需要用到windows提供的几个API函数:CreateToolhelp32Snapshot、Process32First和Process32Next。
函数的简单介绍:
HANDLE WINAPI CreateToolhelp32Snapshot(
__in DWORD dwFlags,
__in DWORD th32ProcessID
);
函数功能:创建指定进程的快照,快照包括进程的堆栈、模块、线程;
参数:
dwFlags:获取系统进程快照的类型;当指定为TH32CS_SNAPPROCESS,表示在快照中包括系统中的所有进程,此时将忽略th32ProcessID的设置。
th32ProcessID:指定要获取进程快照的进程ID;为0表示当前进程;此参数只有在dwFlags设置了TH32CS_SNAPHEAPLIST或者TH32CS_SNAPMODULE后才有效。
返回值:当函数调用成功返回快照句柄,否则返回INVALID_HANDLE_VALUE。在得到系统进程快照句柄后,需要调用Process32First函数查找系统进程快照中的第一个进程。
详情:https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot
Process32First函数
BOOL WINAPI Process32First(
__in HANDLE hSnapshot,
__in_out LPPROCESSENTRY32 lppe
);
函数功能:获取进程快照中的第一个进程信息
参数:
hSnapshot:系统进程快照的句柄;
Lppe:指向PROCESSNTRY结构的结构体指针,进程的详细信息保存在此结构体中:
typedef struct tagPROCESSENTRY32 {
DWORD dwSize;//结构大小
DWORD cntUsage;//此进程的引用计数
DWORD th32ProcessID;//进程ID
ULONG_PTR th32DefaultHeapID;//进程默认堆ID
DWORD th32ModuleID;//进程模块ID
DWORD cntThreads;//此进程开启的线程计数
DWORD th32ParentProcessID;//父进程ID
LONG pcPriClassBase;//线程优先权
DWORD dwFlags;//保留
TCHAR szExeFile[MAX_PATH];//进程名
} PROCESSENTRY32,
*PPROCESSENTRY32;
返回值:当函数列举到进程时返回true,否则返回false。
详情:https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-process32first
Process32Next函数:
BOOL WINAPI Process32Next(
__in HANDLE hSnapshot,
__in_out LPPROCESSENTRY32 lppe
);
函数功能:获取进程快照中下一个进程信息;
参数和返回值与Process32Next函数基本一致
详情:https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-process32next
OpenProcess函数:
HANDLE OpenProcess(
DWORD dwDesiredAccess, //想拥有的该进程的访问权限
BOOL bInheritHandle, //所得到的进程句柄是否可以被继承
DWORD dwProcessId//需要被打开的进程的PID
);
函数功能:打开已存在的进程对象,返回进程句柄;
返回值:函数成功,返回指定进程的句柄,失败返回NULL。
具体的实现代码:
std::vector<HANDLE> GetProcessHandle(LPCWSTR lpName)
{
DWORD dwPid = 0;
HANDLE hProcess = NULL;
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
std::vector<HANDLE> hProcessGroup;
do{
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//获取系统所有进程的快照
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
//日志
break;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcessSnap, &pe32))//获取第一个进程信息
{
//日志
CloseHandle(hProcessSnap);
break;
}
int namelen = 200;
char name[201] = { 0 };
do
{
if (NULL != wcsstr(pe32.szExeFile, lpName)) {//查找匹配字符串
dwPid = pe32.th32ProcessID;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);//获取进程句柄
hProcessGroup.push_back(hProcess);
}
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);//记得释放句柄
}while(0);
return hProcessGroup;
}
这里使用的vector存储多个进程句柄,是因为实际系统中,可能有多个同名的进程,比如Chrome每个页面都是一个进程。
到这里,我们就可以获得的当前系统中指定进程名的所有操作句柄了。
下一篇,将介绍如何使用进程句柄获取进程当前的CPU占用。
本文为作者原创,如需转载,请在评论区征得作者同意,原创链接:https://blog.youkuaiyun.com/anranjingsi/article/details/106104403