Laufende Anwendung beenden
Die Funktion beendet den Prozess, der mit dem übergebenen Exe-Namen oder der angegebenen Prozess-ID übereinstimmt. Sollten mehrere Prozesse desselben Exe-Namens laufen, so wird entweder der zuerst gefundene geschlossen (AKillAll = False) oder alle (AKillAll = True) – diese Angabe ist natürlich nur beim Beenden des Prozesses über den Prozessnamen möglich. Wenn der Prozess mit allen gestarteten Kind-Prozessen beendet werden soll, muss AKillStructure auf True gesetzt werden.
Sobald der Prozess (sowie alle Unterprozesse) erfolgreich beendet wurde, wird True zurückgegeben.
Uses TLHelp32; Function KillTask(Const APID: Cardinal; Const AKillStructure: Boolean = False): Boolean; Overload; Var P: TProcessEntry32; H: THandle; D: DWORD; TP: TTokenPrivileges; hToken: THandle; hProcess: Cardinal; Goon: Boolean; Function IsWinNT: Boolean; Var VI: TOSVersionInfo; Begin VI.dwOSVersionInfoSize := SizeOf(VI); Result := False; If GetVersionEx(VI) Then Result := VI.dwPlatformId = VER_PLATFORM_WIN32_NT; End; Begin Result := False; P.dwSize := SizeOf(P); H := CreateToolHelp32Snapshot(TH32CS_SnapProcess, 0); Goon := True; Try If Process32First(H, P) Then Begin Result := True; Repeat If P.th32ProcessID = APID Then Begin If IsWinNT Then Begin If OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken) Then Begin LookupPrivilegeValue(NIL, 'SeDebugPrivilege', TP.Privileges[0].Luid); TP.PrivilegeCount := 1; TP.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED; D := 0; AdjustTokenPrivileges(hToken, False, TP, 0, PTokenPrivileges(NIL)^, D); CloseHandle(hToken); End; End; hProcess := OpenProcess(Process_Terminate, False, P.th32ProcessID); Goon := False; If hProcess 0 Then Try Result := TerminateProcess(hProcess, 0) And Result; If WaitForSingleObject(hProcess, INFINITE) WAIT_OBJECT_0 Then Result := False; Finally CloseHandle(hProcess); End; End Else If (AKillStructure) And (P.th32ParentProcessID = APID) Then Result := KillTask(P.th32ProcessID, True) And Result; Until (Not Process32Next(H, P)) Or ((Not Goon) And (Not AKillStructure)); End; Finally CloseHandle(H); End; End; Function KillTask(Const AExeName: String; Const AKillAll: Boolean = False; Const AKillStructure: Boolean = False): Boolean; Overload; Var P: TProcessEntry32; H: THandle; Begin Result := False; P.dwSize := SizeOf(P); H := CreateToolHelp32Snapshot(TH32CS_SnapProcess, 0); Try If Process32First(H, P) Then Begin Result := True; Repeat If AnsiLowerCase(P.szExeFile) = AnsiLowerCase(AExeName) Then Begin Result := KillTask(P.th32ProcessID, AKillStructure) And Result; If Not AKillAll Then Break; End; Until (Not Process32Next(H, P)); End; Finally CloseHandle(H); End; End;
Wenn der Prozess auf diese Weise beendet wird, ist Datenverlust möglich. Der Prozess wird beendet, ohne dass dabei Rücksicht auf eventuelle Rückmeldungen genommen wird. Wenn Prozesse, die nicht unter dem eigenen Benutzerkonto ausgeführt werden (wie Systemprozesse), beendet werden sollen, sind Administratorenrechte erforderlich.
Wenn nur versucht werden soll, den Prozess dazu zu bringen, sich selbst zu beenden, kann folgende Prozedur verwendet werden:
Function EnumWindowsCallback(WND: HWND; lParam: LPARAM): Boolean; StdCall; Var PID: Cardinal; Wait: Boolean; Begin Result := True; If GetParent(WND) = 0 Then GetWindowThreadProcessID(WND, PID); If (lParam And (-1)) = -1 Then Begin Wait := True; lParam := (lParam And (Not (-1))); End Else Wait := False; If PID = lParam Then If Wait Then SendMessage(WND, WM_CLOSE, 0, 0) Else PostMessage(WND, WM_CLOSE, 0, 0); End; Procedure TryKillTask(PID: Cardinal; Wait: Boolean = True); Var Flag: LPARAM; Begin If Wait Then Flag := PID And (-1) Else Flag := PID; EnumWindows(@EnumWindowsCallback, Flag); End;
Wenn TryKillTask aufgerufen wird, muss die Prozess-ID übergeben werden (diese kann wie in der Routine in „KillTask mit String“ ermittelt werden). Wenn Wait True ist, pausiert das eigene Programm, bis das Fremdprogramm die Nachricht verarbeitet hat – falls sich also ein Dialog öffnet (wie „Wollen Sie speichern?“), wartet das eigene Programm darauf. Während dieser Zeit kann es nicht bedient werden. Um sicher zu gehen, könnte man noch versuchen, anschließend die Existenz dieses Taskes zu überprüfen (oder einfach KillTask mit der PID direkt aufrufen – falls der Task bereits beendet wurde, geschieht nichts).