psapi.h

使用 psapi.h 會比較麻煩,得到的資訊也比 tlhelp32.h 方式不會比較少,這個例子只是提供簡單的資訊出來而已。使用前需要先連 psapi.lib。由於它的函式引數都特別長,所以這裡會每個引數都一個段行,如果覺得原始碼看得很吃力可以上 MSDN 查詢相關資訊。

程式碼

// ==================================
// filename: ListProcess.cpp
// compiler: vs2008
// author  : EdisonX (Edison.Shih.)
// ref        : MSDN
//   
//   **** all rights reserve ****
// ==================================
#include <windows.h>
#include <psapi.h>
#include <stdio.h>
#pragma comment(lib, "psapi.lib")

void ListProcess(DWORD PID)
{
        HANDLE hProcess;
        char ProcessName[MAX_PATH] = "<unknow>";
        HMODULE hmodule;
        DWORD ret_size;

        // 4. 調用 OpenProcess, 註三
        hProcess = OpenProcess(
                PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, // access rights
                FALSE, // inherit this handle or not
                PID);

        // 5. 取得 Process name
        if(hProcess != NULL){
                // 註四
                if(EnumProcessModules(
                        hProcess,
                        &hmodule,
                        sizeof(hmodule),
                        &ret_size
)){
                       
                        GetModuleBaseName(
                                hProcess,
                                hmodule,
                                ProcessName,
                                sizeof(ProcessName)/sizeof(char))
;
                }
        }

        // 6. 顯示相關資訊
        printf("(%08x):%s\n", PID, ProcessName);
        CloseHandle(hProcess);
}

int main()
{
        DWORD ProcessIDArray[1000];
        DWORD ret_size=0, process_cnt;
        unsigned i;

        // 1. 調用 EnumProcesses
        if(!EnumProcesses(
                ProcessIDArray,
                sizeof(ProcessIDArray),
                &ret_size)){

                printf("EnumProcesses fail.\n");
                return EXIT_FAILURE;
        }

        // 2. 計算實際 process 個數
        process_cnt = ret_size / sizeof(DWORD);

        // 3. 利用 OpenProcess 取得程序內容
        for(i=0; i<process_cnt; i++){
                ListProcess(ProcessIDArray[i]);
        }

        return EXIT_SUCCESS;
}

[註三]  OpenProcess 原型

HANDLE WINAPI OpenProcess(
  __in  DWORD dwDesiredAccess,
  __in  BOOL bInheritHandle,
  __in  DWORD dwProcessId
);

dwDesiredAccess

這裡會要求一個 access right,相關知識實在是太多了,特別是安裝性部份,有興趣上 MSDN 查相關說明。這裡由於只是要尋訪 process ,所以設成 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ。這裡的 flag 設定很重要!每個 flag 可以做的事幾乎就會配用到另一個 API ,相關 flag 如下說明

<所有物件之標準 access right>

(1) DELETE : 請求刪除
(2) READ_CONTROL: 請求讀取安全性
(3) SYNCHRONIZE: 同步使用
(4) WRITE_DAC: 請求修改安全性之 DACL
(5) WRITE_OWNER: 請求更改安全性擁有者(owner)

<特定 process 之 access right>

(1) PROCESS_ALL_ACCESS: 請求所有可能之 access rights
(2) PROCESS_CREATE_PROCESS: 請求建立 process
(3) PROCESS_CREATE_THREAD: 請求建立 thread
(4) PROCESS_DUP_HANDLE: 使用 DuplicateHandle 請求 dup handle
(5) PROCESS_QUERY_INFORMATION: 請求提供 process 相關資訊
(6) PROCESS_QUERY_LIMITED_INFORMATION: 請求提供 process 相關資訊
(7) PROCESS_SET_INFORMATION: 請求設定 process 相關資訊
(8) PROCESS_SET_QUOTA: 請求設置記憶體限制
(9) PROCESS_SUSPEND_RESUME: 請求監控或 resume 一 process
(10) PROCESS_TERMINATE: 請求結束 process
(11) PROCESS_VM_OPERATION: 請求在 process 之 address space 進行操作
(12) PROCESS_VM_READ: 請求讀取 process 之 memory
(13) PROCESS_VM_WRITE: 請求寫入 process 之 memory
(14) SYNCHRONIZE: 請求等待 process 之結束。

bInheritHandle

如果設成 TRUE,則由此 process 所衍生之 process 可繼承其 handle;反之則不繼承。

dwProcessID

這沒什麼好說的, process ID。

[註四]  EnumProcessModules 原型

EnumProcessModules(
  __in   HANDLE hProcess,
  __out  HMODULE *lphModule,
  __in   DWORD cb,
  __out  LPDWORD lpcbNeeded
}

這部份用法相似的有 EnumProcesses、EnumProcessModules、EnumDeviceDrivers。
全部都是先給一個 DWORD 陣列,這個陣列要給多大?MSDN 上的註解是說,如果你不知道有多少 process 、不知道有多少 module 的話,就開大一點給它,不然到時爆了反而尷尬。用法都差不多,順序如下

A. 開一個 DWORD 靜態陣列 array[2000];
B. 宣告變數 DWORD ret_Size; 呼叫相關函式後,會把使用的 bytes 數存進去。
C. 宣告相關的 HMODULE 還是 HANDLE 變數。
D. 丟進函式裡面。

不熟的話再回去看原始碼看幾次就懂了。

edisonx 發表在 痞客邦 PIXNET 留言(0) 人氣()