![]() |
Klasse zum Beenden eines Prozesses
Ich habe hier eine Klasse zum Beenden eine Prozesses, die ich mal zur Diskussion stellen wollte, ob ich da was vergessen habe:
Delphi-Quellcode:
Was mir noch etwas Kopfzerbrechen breitet ist, dass bei einem TimeOut von 0 Millisekunden WAIT_TIMEOUT aufgerufen wird und der Prozess trozdem beendet wird. Damit hängt auch zusammen, dass ich nicht recht weiß, wie ich zurückgeben kann, dass der Prozess erfolgreich beendet wurde. Möglich wäre eine Rückgabe von True bzw. Falls oder das auslösen eines entsprechenden Ereignisses.
// Klasse zum Benden eines Processes mittels TerminateProcess
// Class for terminating a process via TerminateProcess // Michael Puff [http://www.michael-puff.de] unit MpuKillProcessCls; interface uses Windows, SysUtils, TlHelp32; type TKillProcess = class(TObject) private FProcessFile: string; FProcessID: Integer; FTimeOut: Cardinal; procedure GetProcessID; public property ProcessFile: string read FProcessFile write FProcessFile; property TimeOutMSecs: Cardinal read FTimeOut write FTimeOut; constructor Create(ProcessFile: string); procedure Kill; end; implementation constructor TKillProcess.Create(ProcessFile: string); begin FProcessFile := ProcessFile; FTimeOut := 0; GetProcessID; end; procedure TKillProcess.GetProcessID; var ProcessSnapShot: THandle; pe32: TProcessEntry32; begin ProcessSnapShot := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0); if ProcessSnapShot <> INVALID_HANDLE_VALUE then begin pe32.dwSize := SizeOf(ProcessEntry32); if Process32First(ProcessSnapShot, pe32) = true then begin while Process32Next(ProcessSnapShot, pe32) = true do begin if pos(LowerCase(FProcessFile), LowerCase(pe32.szExeFile)) <> 0 then FProcessID := pe32.th32ProcessID; end; end else begin RaiseLastOSError; end; end else begin RaiseLastOSError; end; CloseHandle(ProcessSnapShot); if FProcessID = 0 then raise Exception.Create('Process not found'); end; procedure TKillProcess.Kill; var ProcessHandle: Cardinal; WFSOReturnCode: DWORD; begin ProcessHandle := OpenProcess(SYNCHRONIZE or PROCESS_TERMINATE, False, FProcessID); if ProcessHandle <> 0 then begin if TerminateProcess(ProcessHandle, 0) then begin WFSOReturnCode := WaitForSingleObject(ProcessHandle, FTimeOut); case WFSOReturnCode of WAIT_TIMEOUT: begin if FTimeOut > 0 then raise Exception.Create('Timeout'); end; WAIT_FAILED: begin RaiseLastOSError; end; end; end else begin RaiseLastOSError; end; end else begin RaiseLastOSError; end; end; end. |
AW: Klasse zum Beenden eines Prozesses
Ich habe so etwas noch nie gebraucht, aber könnte der Benutzer des Codes evtl. auch andere Daten zum beenden eines Programms haben? Somit wäre ein weiterer Konstruktor zu bauen.
Es gibt doch zudem das Problem dass wenn eine Anwendung gleich zwei mal geöffnet ist: welche Instanz wird beendet? (habe mir den Code nicht ganz genau angeschaut) Ebenso könntest du ein ForceKill einbauen, welches nach dem Timeout das Programm nach Möglichkeit wirklich schließt?! Geht sowas überhaupt? |
AW: Klasse zum Beenden eines Prozesses
Es wird der Prozess beendet, der zu erst in der Liste gefunden wird.
Welche Daten meinst du? Den Fenstertitel? Dann wäre es aber ein Fenster-Schließer. ;) Wenn der Prozess auch nach dem TimeOut nicht geschlossen werden konnte, dann wird es danach mit hoher Wahrscheinlichkeit auch nicht funktionieren. |
AW: Klasse zum Beenden eines Prozesses
Von diesem Schließen-Gedöns selbst habe ich keine Ahnung ;) Habe da nur an das Herunterfahren von Windows gedacht. Das gibt jeder Anwendung ja auch x Sekunden Zeit. Wenn die Anwendungen nicht "fähig" ist, sich in der Zeit zu beenden, dann wird es eben mit Gewalt beendet -- bist du nicht willig.... :mrgreen: Daher auch die Idee mit dem ForceKill.
Das mit dem ersten Programm in der Liste ist halt so eine Sache. Vielleicht ist es genau das Programm welches man nicht schließen will, wenn zwei offen sind ;) Vielleicht wäre hier ein gewissen Schalte gut, wobei ich nicht weiß, wie man das umgehen sollte. Ich denke, dass es zunächst echt dabei belassen solltest. Außer der Benutzer hat mehr Informationen, wie die ProcessID z.B. Vielleicht wäre ein Filter auch hilfreich: Schließe Prozess...
Ist das Schließen eines Prozesses auf einem anderen Rechner irgendwie möglich? So à la Fernwartung. -- EDIT - Wie sieht es mit einer Lizenz für den Quellcode aus? - und was mir gerade aufgefallen ist: TProcessEntry32 <- heißt das, dass nur 32-bit Programme erkannt werden? Oder klappt das auch mit 64-bit Programmen?! |
AW: Klasse zum Beenden eines Prozesses
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
|
AW: Klasse zum Beenden eines Prozesses
Zitat:
Zitat:
nicht daß jemand eine Datei sucht und zufällig ein Verzeichnis genauso heißt. Und ob es sich auch um den kompletten Namen handelt, nicht daß man nach "ample.exe" sucht und die "example.exe" schließt. eventuell so? (k.A. ob's richtig ist)
Delphi-Quellcode:
oder
s := LowerCase(FProcessFile);
s2 := '\' + LowerCase(pe32.szExeFile); if (s = '') or (s[1] <> '\') then Insert('\', s, 1); if Pos(s, s2) = Length(s2) - Length(s1) + 1 then ...
Delphi-Quellcode:
s := LowerCase(FProcessFile);
s2 := '\' + LowerCase(pe32.szExeFile); if (s = '') or (s[1] <> '\') then Insert('\', s, 1); Delete(s2, 1, Length(s2) - Length(s1)); if s = s2 then ... Zitat:
|
AW: Klasse zum Beenden eines Prozesses
Zitat:
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
if LowerCase(FProcessFile) = LowerCase(pe32.szExeFile)...
|
AW: Klasse zum Beenden eines Prozesses
Zitat:
So kann ich einen hängenden Prozess immer killen: 1. NotePad.EXE öffnen, irgendwas eintippen, 2. User ausloggen. 3. NotePad.EXE fragt mich, ob ich die ungesicherten Änderungen speichern will, 4. kurz warten, denn 5. der hängende Prozess verschwindet GARANTIERT. 6. Dann breche ich den ganzen Logout-Vorgang ab, indem ich 7. bei der Notpad-Frage auf 'Abbrechen' klicke. Funktioniert immer! Natürlich werden auch diverse andere Programme beendet, auch Dienste. Das ist also die letzte aller Möglichkeiten. Aber wie macht Windows das? |
AW: Klasse zum Beenden eines Prozesses
Ein setter für
Delphi-Quellcode:
ist nötig, da die PID nur im Konstruktor gehohlt wird. Nicht das falsche Prozesse ungewollt beendet werden.
ProcessFile
|
AW: Klasse zum Beenden eines Prozesses
Zitat:
|
AW: Klasse zum Beenden eines Prozesses
Zitat:
--EDIT Nein, war nur eine ![]() |
AW: Klasse zum Beenden eines Prozesses
Zitat:
Delphi-Quellcode:
bringt momentan nichts, außer evtl ungewollte Verhaltensweisen.
public
property ProcessFile: string read FProcessFile write FProcessFile; |
AW: Klasse zum Beenden eines Prozesses
Oh. Danke für den Hinweis.
|
AW: Klasse zum Beenden eines Prozesses
Zitat:
Delphi-Quellcode:
und jetzt lass mal dein
C:\Programme\Example.exetus\Demo.exe
Delphi-Quellcode:
darauf los. :stupid:
POS('ample.exe'
Zitat:
Delphi-Quellcode:
.
if AnsiSameText(FProcessFile, pe32.szExeFile) then...
PS: LowerCase = nur A bis Z wird übersetzt AnsiLowerCase = alle Zeichen (ab D2009 ist AnsiLowerCase standardmäßig Unicode) Und warum so lang ... so könnte man auch nach
Delphi-Quellcode:
,
Demo.exe
Delphi-Quellcode:
oder
Example.exetus\Demo.exe
Delphi-Quellcode:
suchen. :angel2:
C:\Programme\Example.exetus\Demo.exe
(und wehe einer sagt was über meine exetus-Wortschöpfung :warn: ) |
AW: Klasse zum Beenden eines Prozesses
Zwei Vorschläge auch von mir:
1. Der Parameter im Konstruktor sollte const sein, da er nicht verändert wird. 2. Ich würde eine statische Klassenfunktion mit Dateiname und Timeout vorschlagen, die ohne Umwege über eine Instanziierung einen Prozess killen kann. Für einfach gelagerte Fälle oder falls man keine Wiederverwendung anstrebt, fände ich das ganz praktisch. Viele Grüße |
AW: Klasse zum Beenden eines Prozesses
@himitsu: Wenn ich mich recht erinnere steht pe32.szExeFile nur der Prozessname, also kein Pfad.
@Mirage: Erster Vorschlag angenommen, zweiter muss noch überdacht werden. |
AW: Klasse zum Beenden eines Prozesses
Zitat:
Hätte den vollständigen Pfad erwartet (wie bei Application.ExeName :stupid: ), da ja mehrere Dateien auf einer Festplatte den selben Namen besitzen können. |
AW: Klasse zum Beenden eines Prozesses
Anbei die überarbeitet Version mit euren Vorschlägen:
Delphi-Quellcode:
Demo:
// Klasse zum Benden eines Processes mittels TerminateProcess
// Class for terminating a process via TerminateProcess // Michael Puff [http://www.michael-puff.de] // 2010-11-21 unit MpuKillProcessCls; interface uses Windows, SysUtils, TlHelp32; type TOnTerminated = procedure(Sender: TObject) of Object; TKillProcess = class(TObject) private FFilename: string; FProcessID: Cardinal; FTimeOut: Cardinal; FOnTerminated: TOnTerminated; procedure GetProcessID; procedure SetFilename(const Value: string); procedure SetPID(Value: Cardinal); public property Filename: string read FFilename write SetFilename; property PID: Cardinal read FProcessID write SetPID; property TimeOutMSecs: Cardinal read FTimeOut write FTimeOut; property OnTerminated: TOnTerminated read FOnTerminated write FOnTerminated; constructor Create; procedure Kill; end; implementation constructor TKillProcess.Create; begin FTimeOut := 0; end; procedure TKillProcess.GetProcessID; var ProcessSnapShot: THandle; pe32: TProcessEntry32; begin ProcessSnapShot := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0); if ProcessSnapShot <> INVALID_HANDLE_VALUE then begin pe32.dwSize := SizeOf(ProcessEntry32); if Process32First(ProcessSnapShot, pe32) then begin while Process32Next(ProcessSnapShot, pe32) do begin if AnsiSameText(FFilename, pe32.szExeFile) then FProcessID := pe32.th32ProcessID; end; end else begin RaiseLastOSError; end; end else begin RaiseLastOSError; end; CloseHandle(ProcessSnapShot); if FProcessID = 0 then raise Exception.Create('Process not found'); end; procedure TKillProcess.Kill; var ProcessHandle: Cardinal; WFSOReturnCode: DWORD; begin ProcessHandle := OpenProcess(SYNCHRONIZE or PROCESS_TERMINATE, False, FProcessID); if ProcessHandle <> 0 then begin if TerminateProcess(ProcessHandle, 0) then begin WFSOReturnCode := WaitForSingleObject(ProcessHandle, FTimeOut); case WFSOReturnCode of WAIT_TIMEOUT: begin if FTimeOut > 0 then raise Exception.Create('Timeout'); end; WAIT_FAILED: begin RaiseLastOSError; end; WAIT_OBJECT_0: begin if Assigned(OnTerminated) then OnTerminated(self); end; end; end else begin RaiseLastOSError; end; end else begin RaiseLastOSError; end; end; procedure TKillProcess.SetFilename(const Value: string); begin FFilename := Value; GetProcessID; end; procedure TKillProcess.SetPID(Value: Cardinal); begin FProcessID := Value; end; end.
Delphi-Quellcode:
Bestehendes Problem ist noch die Benachrichtigung beim erfolgreichen Beenden. Da habe ich noch keine Idee, die mir gefällt. Problem ist der TimeOut von 0. Da geht er auch in den WAIT_TIMEOUT Zweig rein und der Prozess könnte trotzdem erfolgreich beendet worden sein - oder auch nicht. Das ist das Problem. Und bis das Problem nicht gelöst ist, kann und will ich den Code nicht offiziell veröffentlichen. Zur Zeit habe ich nur ein Ereignis, wenn das Objekt signalisiert wird.
program Project2;
{$APPTYPE CONSOLE} uses SysUtils, MpuKillProcessCls in 'MpuKillProcessCls.pas'; type TMain = class(TObject) public procedure OnTerminated(Sender: TObject); end; procedure TMain.OnTerminated(Sender: TObject); begin Writeln('Prozess beendet'); end; var Main: TMain; KillProcess: TKillProcess; begin Main := TMain.Create; try KillProcess := TKillProcess.Create; try try KillProcess.OnTerminated := Main.OnTerminated; KillProcess.TimeOutMSecs := 5000; KillProcess.Filename := 'notePad++.exe'; //KillProcess.PID := 2696; KillProcess.Kill; except on E: Exception do Writeln(E.Message); end; finally KillProcess.Free; end; finally Main.Free; end; Readln; end. |
AW: Klasse zum Beenden eines Prozesses
|
AW: Klasse zum Beenden eines Prozesses
Gut, dass ihr noch mal drüberguckt. Das CloseHandle habe ich übersehen.
Braucht man für SE_DEBUG_NAME nicht bestimmte rechte? Ich werde es aber mal ausprobieren. Scheint zu gehen. Danke für die Hinweise. Allerdings habe ich immer noch das Problem mit der Vollzugsmeldung beim erfolgreichen beenden bei WAIT_TIMEOUT. |
AW: Klasse zum Beenden eines Prozesses
irgendwie vermisse ich noch an geeigneter Stelle ein
Delphi-Quellcode:
, sonst kann die Konstallation eintreten, dass willkürlich ein Prozess terminiert wird (Prozess nicht gefunden, FProcessID steht zufällig auf einem Wert, der ein existierenden Prozess bezeichnet).
FProcessID:=0;
|
AW: Klasse zum Beenden eines Prozesses
Es ist ja bekannt, dass TerminateProcess() einen Prozess nicht unbedingt ordnungsgemäß beendet.
Darum werfe ich die Funktion SafeTerminateProcess vom Artikel ![]() Siehe auch eine ![]() Anbei noch 2 Funktionen zum Überprüfen, ob ein Prozess beendet wurde:
|
AW: Klasse zum Beenden eines Prozesses
Irgendwie verstehe ich nicht, warum das hier in eine Klasse gegossen wird.
Eine schnöde function/procedure hätte es auch getan. Aber nun erzeuge ich eine Instanz um eine andere Instanz zu beenden und dann beende ich diese Beende-Instanz. Klingt irgendwie nicht logisch. Was für mich Sinn ergeben würde, wäre eine Klasse, die zu einem Prozess Informationen gibt. Wieviele Instanzen sind aktiv, wie hoch ist der Speicherverbrauch, etc. Ja, die Möglichkeit einen Prozess zu killen gehört da auch rein. Als Events würden sich anbieten, wenn einen neue Instanz auftaucht und wenn eine Instanz verschwindet. Dann würde sich auch eine Klasse rechtfertigen. Wäre also eine TaskManagerKlasse für jeweils eine Anwendung. |
AW: Klasse zum Beenden eines Prozesses
Zitat:
|
AW: Klasse zum Beenden eines Prozesses
Zitat:
|
AW: Klasse zum Beenden eines Prozesses
Zitat:
Zitat:
Zitat:
Zitat:
@Toms: Richtig mittels GetExitCodeProzess könnte ich bei einem TimeOut von 0 Millisekunden prüfen, ob der Prozess beendet wurde. |
AW: Klasse zum Beenden eines Prozesses
Man muss eine Instanz von
Delphi-Quellcode:
erzeugen um eine andere Instanz zu beenden.
TKillProcess
Das halte ich für unlogisch. Mit der Klasse
Delphi-Quellcode:
fragst du eh schon die Eigenschaften des Prozesses ab, weil du ja zu einem ExeNamen die ProcessID ermitteln möchtest.
TKillProcess
Für mich würde die Klasse nur dann einen Sinn ergeben, wenn die Klasse eine längere Daseinsberechtigung als nur zum reinen Killen des Prozesses. Eine Möglichkeit wäre es doch erst beim Aufrufen der Methode Kill die ProcessID zu ermitteln und dann zu killen. Dann erzeugt man sich die Klasse, gibt den ExeNamen an und immer wenn man diese Exe aus dem Speicher haben möchte ruft man einfach Kill auf und die Prozesse werden gelöscht. Das vermisse ich auch irgendwie, wenn eine Anwendung n-fach gestartet wurde, dann wird nur eine gelöscht. Welche das ist, hängt davon ab, welche als letzte in der Prozess-Liste steht. Somit würde ich erwarten, dass bei der Angabe eines ExeNamens alle Prozesse gelöscht werden, die dazu gehören. Dann wäre das Verhalten auch eindeutig und nicht ein Zufallsprodukt. Ei Argument, was noch gegen die Verwendung einer Klasse spricht ist, dass es bei dem jetzigen Aufbau zu Fehlern kommen kann, die man so eigentlich nicht haben will.
Delphi-Quellcode:
Dieses ist durch dein Design so möglich und kann dazu führen, dass
KP := TKillProcess.Create;
try KP.FileName := 'notepad++.exe'; // Jetzt ermittelt die Klasse die PID // Ich muss jetzt noch ein paar Sachen prüfen, die so eine gewisse Zeit dauern Sleep( 10000 ); // So als Dummy-Beschäftigung KP.Kill; // Ja, ist denn die PID von eben immer noch die richtige? finally KP.Free; end; a) Der Prozess ist schon beendet worden (von wem auch immer) Wenn Kill jetzt einen Fehler wirft, ist der Fehler dann nicht verwirrend. Ich möchte das als Resultat der Prozess nicht mehr im System läuft. Das ist ja auch erreicht worden (zwar nicht ursächlich durch die Klasse, aber das Resultat ist das Gleiche) aber ich bekomme einen Fehler. Könnte man evtl. noch mit leben b) Der Prozess ist schon beendet worden( von wem auch immer) und ein völlig anderer Prozess (z.B. outlook.exe) hat jetzt die gleiche PID bekommen wie notepad++.exe vorher hatte. Nun wird mit Kill nicht notepad++.exe sondern outlook.exe geschlossen |
AW: Klasse zum Beenden eines Prozesses
Zitat:
Ich sage nur, daß es ab Vista größere Probleme aufgrund der Sitzungsisolation und der Integritätsniveaus kommen wird. Ob und/oder wie das beherzigt wird, ist mir an Ende egal :zwinker: |
AW: Klasse zum Beenden eines Prozesses
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Ei Argument, was noch gegen die Verwendung einer Klasse spricht ist, dass es bei dem jetzigen Aufbau zu Fehlern kommen kann, die man so eigentlich nicht haben will. Zitat:
Delphi-Quellcode:
KP := TKillProcess.Create;
try // Ich muss jetzt noch ein paar Sachen prüfen, die so eine gewisse Zeit dauern Sleep( 10000 ); // So als Dummy-Beschäftigung KP.FileName := 'notepad++.exe'; // Jetzt ermittelt die Klasse die PID KP.Kill; // Ja, ist denn die PID von eben immer noch die richtige? finally KP.Free; end; |
AW: Klasse zum Beenden eines Prozesses
Hmmm, wenn man eine Klasse nur dann korrekt benutzen kann, indem man x Vorgaben einhält, und diese Vorgaben aber nur durch ein ungeschicktes Design der Klasse herrühren, dann würde ich immer das Design der Klasse ändern.
Ansonsten muss man an solche Klassen immer den Hinweis kleben: Zitat:
![]() Prozess und Instanz Wenn eine Anwendung x-fach gestartet ist, und man findet somit im System auch x Prozesse, so kann man im übertragenen Sinne auch von Instanzen sprechen. Ich wollte damit nur sprachlich darstellen, dass hier etwas erzeugt wird um etwas anderes zu zerstören und dann muss ich diesen Zerstören selber wieder zerstören, weil dieser nutzlos geworden ist (es sei denn ich weise diesem wieder einen neuen Wert zu) |
AW: Klasse zum Beenden eines Prozesses
OK, überredet. ;)
|
AW: Klasse zum Beenden eines Prozesses
Zitat:
|
AW: Klasse zum Beenden eines Prozesses
Madshi hatte glaube ich eine CreateRemoteThread, die auch über Sitzungen funkz. Naja, ich sehe schon wieder ne Menge Virenscanner, die da anschlagen würde.
Und dann einfach PostQuitMessage aufrufen muss auch nicht funkzen. Irgendein Verrückter könnte ein Fenster pro Thread gebaut haben, um Einfrieren zu verhindern. |
AW: Klasse zum Beenden eines Prozesses
Zitat:
|
AW: Klasse zum Beenden eines Prozesses
Aktuelle Version:
Delphi-Quellcode:
Demo:
// Klasse zum Benden eines Processes mittels TerminateProcess
// Class for terminating a process via TerminateProcess // Michael Puff [http://www.michael-puff.de] // 2010-11-22 unit MpuKillProcessCls; interface uses Windows, Messages, SysUtils, TlHelp32; type TOnTerminated = procedure(HasTerminated: Boolean; ProcessExefile: string) of object; TOnProcessNotFound = procedure(ProcessExefile: string) of object; TKillProcess = class(TObject) private FProcessExefile: string; FProcessID: Cardinal; FTimeOut: Cardinal; FOnTerminated: TOnTerminated; FOnProcessNotFound: TOnProcessNotFound; function GetProcessID: Cardinal; procedure SetProcessExefile(const Value: string); procedure SetPID(Value: Cardinal); function EnablePrivilege(const Privilege: string; fEnable: Boolean; out PreviousState: Boolean): DWORD; public property ProcessExefile: string read FProcessExefile write SetProcessExefile; property PID: Cardinal read FProcessID write SetPID; property TimeOutMSecs: Cardinal read FTimeOut write FTimeOut; property OnTerminated: TOnTerminated read FOnTerminated write FOnTerminated; property OnProcessNotFound: TOnProcessNotFound read FOnProcessNotFound write FOnProcessNotFound; constructor Create; procedure Kill; end; implementation constructor TKillProcess.Create; begin FTimeOut := 0; end; function TKillProcess.EnablePrivilege(const Privilege: string; fEnable: Boolean; out PreviousState: Boolean): DWORD; var Token: THandle; NewState: TTokenPrivileges; Luid: TLargeInteger; PrevState: TTokenPrivileges; Return: DWORD; begin PreviousState := True; if (GetVersion() > $80000000) then // Win9x Result := ERROR_SUCCESS else begin // WinNT if not OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, Token) then Result := GetLastError() else try if not LookupPrivilegeValue(nil, PChar(Privilege), Luid) then Result := GetLastError() else begin NewState.PrivilegeCount := 1; NewState.Privileges[0].Luid := Luid; if fEnable then NewState.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED else NewState.Privileges[0].Attributes := 0; if not AdjustTokenPrivileges(Token, False, NewState, SizeOf(TTokenPrivileges), PrevState, Return) then Result := GetLastError() else begin Result := ERROR_SUCCESS; PreviousState := (PrevState.Privileges[0].Attributes and SE_PRIVILEGE_ENABLED <> 0); end; end; finally CloseHandle(Token); end; end; end; function TKillProcess.GetProcessID: Cardinal; var ProcessSnapShot: THandle; pe32: TProcessEntry32; ProcessID: Cardinal; begin ProcessID := 0; ProcessSnapShot := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0); if ProcessSnapShot <> INVALID_HANDLE_VALUE then begin pe32.dwSize := SizeOf(ProcessEntry32); if Process32First(ProcessSnapShot, pe32) then begin while Process32Next(ProcessSnapShot, pe32) do begin if AnsiSameText(FProcessExefile, pe32.szExeFile) then begin ProcessID := pe32.th32ProcessID; Break; end; end; end else begin RaiseLastOSError; end; end else begin RaiseLastOSError; end; CloseHandle(ProcessSnapShot); if ProcessID = 0 then begin if Assigned(OnProcessNotFound) then OnProcessNotFound(FProcessExefile); end; Result := ProcessID; end; procedure TKillProcess.Kill; var EnablePrivelege: DWORD; PreviousPriviliegeState: Boolean; ProcessHandle: Cardinal; WFSOReturnCode: DWORD; begin FProcessID := GetProcessID; if FProcessID <> 0 then begin repeat EnablePrivelege := EnablePrivilege('SE_DEBUG_NAME', true, PreviousPriviliegeState); if EnablePrivelege <> 0 then begin ProcessHandle := OpenProcess(SYNCHRONIZE or PROCESS_TERMINATE, False, FProcessID); if ProcessHandle <> 0 then begin if TerminateProcess(ProcessHandle, 0) then begin WFSOReturnCode := WaitForSingleObject(ProcessHandle, FTimeOut); case WFSOReturnCode of WAIT_TIMEOUT: begin if GetProcessID = 0 then begin if Assigned(OnTerminated) then OnTerminated(True, FProcessExefile); end else begin if Assigned(OnTerminated) then OnTerminated(False, FProcessExefile); Exit; end; if FTimeOut > 0 then begin raise Exception.Create('Timeout'); end; end; WAIT_FAILED: begin RaiseLastOSError; end; WAIT_OBJECT_0: begin if Assigned(OnTerminated) then OnTerminated(True, FProcessExefile); end; end; end else begin RaiseLastOSError; end; CloseHandle(ProcessHandle); end else begin RaiseLastOSError; end; end else begin raise Exception.Create(SysErrorMessage(GetLastError)); end; FProcessID := GetProcessID; until FProcessID = 0; end; end; procedure TKillProcess.SetProcessExefile(const Value: string); begin FProcessExefile := Value; end; procedure TKillProcess.SetPID(Value: Cardinal); begin FProcessID := Value; end; end.
Delphi-Quellcode:
program Project2;
{$APPTYPE CONSOLE} uses SysUtils, MpuKillProcessCls in 'MpuKillProcessCls.pas'; type TMain = class(TObject) public procedure OnTerminated(HasTerminated: Boolean; ProcessExefile: string); procedure OnProcessNotFound(ProcessExefile: string); end; procedure TMain.OnProcessNotFound(ProcessExefile: string); begin Writeln('Fehler. Process ' + ProcessExeFile + ' nicht gefunden.'); end; procedure TMain.OnTerminated(HasTerminated: Boolean; ProcessExefile: string); begin if HasTerminated then Writeln('Prozess ' + ProcessExefile + ' beendet') else Writeln('Fehler beim Beenden des Prozesses ' + ProcessExefile); end; var Main: TMain; KillProcess: TKillProcess; begin Main := TMain.Create; try KillProcess := TKillProcess.Create; try try KillProcess.OnTerminated := Main.OnTerminated; KillProcess.OnProcessNotFound := Main.OnProcessNotFound; KillProcess.TimeOutMSecs := 5000; KillProcess.ProcessExefile := 'photofiltre.exe'; //KillProcess.ProcessExefile := 'svchost.exe'; //KillProcess.PID := 2696; KillProcess.Kill; except on E: Exception do Writeln(E.Message); end; finally KillProcess.Free; end; finally Main.Free; end; Readln; end. |
AW: Klasse zum Beenden eines Prozesses
Ich habe den kompletten Thread jetzt nicht durchgelesen, aber was mir noch fehlen würde, wäre die Möglichkeit, Prozesse anhand des Fenstertitels zu beenden.
|
AW: Klasse zum Beenden eines Prozesses
Immer langsam mit den jungen Pferden. Man muss sich ja noch für Version 2 was aufheben. ;)
|
AW: Klasse zum Beenden eines Prozesses
Zitat:
Auch Dein Zitat:
Delphi-Quellcode:
Das nur so als Ergänzung zu dem ansonsten guten und bewährten (und deshalb auch von mir ursprünglich so übernommenen Code).
if Process32First(ProcessSnapShot, pe32) then
repeat if pos(LowerCase(FProcessFile), LowerCase(pe32.szExeFile)) <> 0 then FProcessID := pe32.th32ProcessID until not Process32Next(ProcessSnapShot, pe32) Gruß Delph-Laie |
AW: Klasse zum Beenden eines Prozesses
Zitat:
Für den Pfad benötigt man deshalb unter NTx beim ersten Eintrag des Modulschnappschusses den Eintrag "szExePath". |
AW: Klasse zum Beenden eines Prozesses
@Delphi-Laie: Du beziehst dich da gerade auf veralteten Code.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:02 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz