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. 丟進函式裡面。
不熟的話再回去看原始碼看幾次就懂了。