網絡安全編程:結束進程
通常情況下,讓程序自行結束是最理想的狀態。在進程正常進行退出時,會調用ExitProcess()函數。利用調用SendMessage()函數發送WM_CLOSE消息到目標窗口的方法,會讓程序正常結束而退出。本文介紹類似任務管理器的功能,強制結束某個指定的進程。
1. 結束指定進程的示例代碼
通過結束一個記事本,說明如何結束其他進程。結束記事本進程的代碼如下:
- #include <Windows.h>
- int main(int argc, char* argv[])
- {
- HWND hNoteWnd = FindWindow(NULL, "無標題 - 記事本");
- if ( hNoteWnd == NULL )
- {
- return -1;
- }
- DWORD dwNotePid = 0;
- GetWindowThreadProcessId(hNoteWnd, &dwNotePid);
- if ( dwNotePid == 0 )
- {
- return -1;
- }
- HANDLE hNoteHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwNotePid);
- if ( hNoteHandle == NULL )
- {
- return -1;
- }
- BOOL bRet = TerminateProcess(hNoteHandle, 0);
- if ( bRet == TRUE )
- {
- MessageBox(NULL, "結束進程成功", NULL, MB_OK);
- }
- CloseHandle(hNoteHandle);
- return 0;
- }
編譯連接上面的程序,然后打開一個空的記事本程序,運行這個編譯好的程序,會發現記事本程序的進程被結束掉了,這里的程序彈出一個簡單的對話框,提示“結束進程成功”。
2. 結束進程所需API函數說明
在上面的程序代碼中,結束進程的API函數一共用到了4個,分別是FindWindow()、GetWindowThreadProcessId()、OpenProcess()和TerminateProcess()。
GetWindowThreadProcessId()函數的定義如下:
- DWORD GetWindowThreadProcessId(
- HWND hWnd,
- LPDWORD lpdwProcessId
- );
參數說明如下。
hWnd:窗口句柄,代碼中的窗口句柄是由 FindWindow()函數獲取的。
lpdwProcessId:該參數是一個指向 DWORD 類型的指針,用戶返回窗口句柄所對應的進程 ID。
GetWindowThreadProcessId()函數在得到進程 ID 后,將進程 ID 傳遞給 OpenProcess() 函數來得到進程的句柄。OpenProcess()函數的定義如下:
- HANDLE OpenProcess(
- DWORD dwDesiredAccess,
- BOOL bInheritHandle,
- DWORD dwProcessId
- );
參數說明如下。
dwDesiredAccess:打開進程欲獲得的訪問權限,該參數為了方便,可以始終為 PROCESS_ALL_ACCESS。
bInheritHandle:指定獲取的句柄是否可以繼承,一般選擇不繼承,傳遞值為 FALSE。
dwProcess:指定欲打開的進程 ID 號,該進程 ID 號是由 GetWindowThreadProcessId()獲得的。
該函數的返回值為進程的句柄,通過這個句柄就可以調用 TerminateProcess()函數來進行結束。TerminateProcess()函數的定義如下:
- BOOL TerminateProcess(
- HANDLE hProcess,
- UINT uExitCode
- );
參數說明如下。
hProcess:欲結束進程的進程句柄,該句柄已經由 OpenProcess()函數得到。
uExitCode:進程的退出碼,通常為 0 值。
通過一些列的API函數,完成了一個結束進程的程序。結束程序時的第一步是得到窗口的句柄,如果這個進程沒有窗口,是不是就沒有辦法通過程序去結束進程了?其實還是有辦法的。
從上面的3個API函數中可以看到,通過進程的窗口可以得到進程的ID,通過進程的ID可以得到進程的句柄。他們內部本身都是有關聯的,因此,在需要使用相關資源時,如果不能直接得到的時候,不妨通過這樣的方式逐步去得到。