假設某天我突發奇想,想要實現:
輸入一個進程名字,輸出該進程的句柄、內存佔用、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.csdn.net/anranjingsi/article/details/106104403