Home » Tipps & Tricks » System » Prozesse » Laufende Anwendung beenden

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).