如何監控windows進程的句柄、內存和cpu(一)

假設某天我突發奇想,想要實現:

輸入一個進程名字,輸出該進程的句柄、內存佔用、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。

詳情:https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess

 

具體的實現代碼:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章