標籤:visual c++ windows核心編程 進程
終止進程的運行
1.主線程的進入點函數返回(最好使用這個方法)。
2.進程中的一個線程調用ExitProcess函數(應該避免使用這種方法)。
3.另一個進程中的線程調用TerminateProcess函數(應該避免使用這種方法)。
4.進程中的所有線程自行終止運行(這種情況幾乎從未發生)。
主線程的進入點函數返回
始終都應該這樣來設計應用程式,即只有當主線程的進入點函數返回時,它的進程才終止運行。這是保證所有線程資源能夠得到正確清除的唯一辦法。讓主線程的進入點函數返回,可以確保下列操作的實現:
該線程建立的任何C++對象將能使用它們的解構函式正確地撤消。
作業系統將能正確地釋放該線程的堆棧使用的記憶體。
系統將進程的結束代碼(在進程的核心對象中維護)設定為進入點函數的返回值。
系統將進程核心對象的返回值遞減1。
ExitProcess函數
主線程的進入點函數(WinMain、wWinMain、main或wmain)返回時,它將返回給C/C++運行期啟動代碼,它能正確地清除該進程使用的所有的C運行期資源。當C運行期資源被釋放之後,C運行期啟動代碼就顯式調用ExitProcess,並將進入點函數返回的值傳遞給它。這解釋了為什麼只需要主線程的進入點函數返回,就能夠終止整個進程的運行。請注意,進程中啟動並執行任何其他線程都隨著進程而一道終止運行。
調用ExitProcess或ExitThread可使進程或線程在函數中就終止運行
可能會導致運行期庫的C,C++資源沒有得到釋放,主線程也沒有的到釋放
#include <windows.h>#include <stdio.h>class CSomeObj{public:CSomeObj(int index){m_index = index;printf("Constructor\r\n");}~CSomeObj(){printf("Destructor %d \r\n",m_index);}public:int m_index;};CSomeObj g_GlobalObj(100);int _tmain(int argc, _TCHAR* argv[]){CSomeObj LocalObj(200);//This shouldn't be hereExitProcess(0);return 0;}
TerminateProcess函數
BOOL TerminateProcess(HANDLE hProcess,UINT fuExitCode);
在任何線程中都能終止另一個進程或者自己本身的進程
只有當無法用另一種方法來迫使進程退出時,才應該使用TerminateProcess。終止啟動並執行進程絕對得不到關於它將終止啟動並執行任何通知,因為應用程式無法正確地清除,並且不能避免自己被撤消(除非通過正常的安全機制)。
這個有點像你的電腦死機藍屏正在啟動並執行程式的資料沒有得到正確的儲存
注意TerminateProcess函數是個非同步啟動並執行函數,你不知道它什麼時間結束
#include <windows.h>#include <stdio.h>typedef DWORD(__stdcall *NtTerminateProcess)(HANDLE, UINT);NtTerminateProcess fNtTerminateProcess = NULL;BOOL ExitProc(HANDLE hProc){HINSTANCE hModule = LoadLibrary(_T("ntdll.dll")); //載入 ntdll.dllif (hModule != 0){fNtTerminateProcess = (NtTerminateProcess)GetProcAddress(hModule, "NtTerminateProcess"); //載入外部DLL函數HANDLE hToken = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)hProc); //獲得進程的最大許可權if (hToken != 0){if (fNtTerminateProcess(hToken, 1) == 0) //關閉程式{printf("End Proc:%d\n", (int)hProc);return TRUE;}else{return FALSE;}}return FALSE;}}int _tmain(int argc, _TCHAR* argv[]){STARTUPINFO si;PROCESS_INFORMATION pi;ZeroMemory(&si, sizeof(si));si.cb = sizeof(si);ZeroMemory(&pi, sizeof(pi));TCHAR szpath[] = TEXT("WORDPAD README.txt");TCHAR lpCommandLine[] = _T("C:\\Windows\\notepad.exe");// Start the child process. if (!CreateProcess(NULL, // No module name (use command line)lpCommandLine, // Command lineNULL, // Process handle not inheritableNULL, // Thread handle not inheritableFALSE, // Set handle inheritance to FALSE0, // No creation flagsNULL, // Use parent's environment blockNULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure&pi) // Pointer to PROCESS_INFORMATION structure){printf("CreateProcess failed (%d)\n", GetLastError());return 0;}//ExitProcess(0);//ExitThread(0);ExitProc(pi.hProcess);//CloseHandle(pi.hProcess);//CloseHandle(pi.hThread);return 0;}
進程終止運行時出現的情況基本上不會發生
當進程終止運行時,下列操作將啟動運行:
1)進程中剩餘的所有線程全部終止運行。
2)進程指定的所有使用者物件和GDI對象均被釋放,所有核心對象均被關閉(如果沒有其他進程開啟它們的控制代碼,那麼這些核心對象將被撤消。但是,如果其他進程開啟了它們的控制代碼,核心對象將不會撤消)。
3)進程的結束代碼將從STILL_ACTIVE改為傳遞給ExitProcess或TerminateProcess的代碼。
4)進程核心對象的狀態變成收到通知的狀態(關於傳送通知的詳細說明,參見第9章)。系統中的其他線程可以掛起,直到進程終止運行。
5)進程核心對象的使用計數遞減1。
BOOL GetExitCodeProcess(HANDLE hProcess,PDWORD pdwExitCode);
#include <Windows.h>#include <tchar.h>#include <strsafe.h>int _tmain(int argc, _TCHAR* argv[]){TCHAR lpCommandLine[] = TEXT("NOTEPAD");STARTUPINFO si;ZeroMemory(&si, sizeof(si));si.cb = sizeof(si);PROCESS_INFORMATION pi;ZeroMemory(&pi, sizeof(pi));SECURITY_ATTRIBUTES ps;ps.bInheritHandle = FALSE;ps.nLength = sizeof(ps);ps.lpSecurityDescriptor = NULL;if (!CreateProcess(NULL,lpCommandLine,&ps,NULL,FALSE,NULL,NULL,NULL,&si,&pi)){printf("CreateProcess failed (%d)\n", GetLastError());return 0;}else{DWORD dwExitCode = NULL;//Close the thread handle as soon as//it is no longer needed!//Suspend our execution until//the child has terminated.WaitForSingleObject(pi.hProcess, INFINITE);//The child process terminated;//get its exit code.if (!GetExitCodeProcess(pi.hProcess,&dwExitCode)){_tprintf(_T("GetExitCodeProcess false"));printf("exitcode failed (%d)\n", GetLastError());}else{ printf("exitcode is %s", dwExitCode);}//Close the process handle as soon as//it is no longer needed.CloseHandle(pi.hThread);CloseHandle(pi.hProcess);}return 0;}
該函數查看進程的核心對象(由hProcess參數來標識),取出核心對象的資料結構中用於標識進程的結束代碼的成員。該結束代碼的值在pdwExitCode參數指向的DWORD中返回。
枚舉系統進程
// EnumProcess.cpp : 定義控制台應用程式的進入點。//#include "stdafx.h"#include <windows.h>#include <tchar.h>#include <strsafe.h>#include <Psapi.h>void PrintProcessNameAndID(DWORD processID){TCHAR szProcessName[MAX_PATH] = _T("<unknown>");//進程ID 開啟進程HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE, processID);if (NULL != hProcess){HMODULE hMod;DWORD cbNeeded;if (EnumProcessModules(hProcess, &hMod, sizeof(hMod),&cbNeeded)){GetModuleBaseName(hProcess, hMod, szProcessName,sizeof(szProcessName) / sizeof(TCHAR));}}_tprintf(_T("(PID: %-4u)\t%20s\n"), processID, szProcessName);CloseHandle(hProcess);}int _tmain(int argc, _TCHAR* argv[]){DWORD aProcesses[1024], cbNeeded, cProcesses;unsigned int i;//枚舉進程的IDif (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))return 0;cProcesses = cbNeeded / sizeof(DWORD);for (i = 0; i < cProcesses; i++)if (aProcesses[i] != 0)PrintProcessNameAndID(aProcesses[i]);_tsystem(_T("PAUSE"));return 0;}
Windows-進程-退出進程