Autor |
Beitrag |
Xabitire
      
Beiträge: 114
Win Xp, Win Vista
D6 PE, D7 PE
|
Verfasst: Mi 03.06.09 16:53
Hi Leute,
ich versuche grad ein laufendes Programm anhand seines Speicherpfades zu finden und dann zu Beenden. Meine bisherige Vorgehensweise war, dass ich zunächst alle Prozesse durchgehe und den zugehörigen Speicherpfad des Prozesses mit dem gegebenen zu vergleichen und somit erst einmal die entsprechende ProzessID herauszufinden. Das klappt so weit auch ganz gut. Jetzt steh ich allerdings vor dem Problem, dass ich von der Id zum Fenster kommen muss, damit ich diesem eine WM_Close-Nachricht schicken kann. Das will aber irgendwie nicht so, wie ich will.
Hier erst mal der relevante Code:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153:
| function IsWinXP: Boolean; begin Result := (Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion = 5) and (Win32MinorVersion = 1); end;
function IsWin2k: Boolean; begin Result := (Win32MajorVersion >= 5) and (Win32Platform = VER_PLATFORM_WIN32_NT); end;
function IsWinNT4: Boolean; begin Result := Win32Platform = VER_PLATFORM_WIN32_NT; Result := Result and (Win32MajorVersion = 4); end;
function IsWin3X: Boolean; begin Result := Win32Platform = VER_PLATFORM_WIN32_NT; Result := Result and (Win32MajorVersion = 3) and ((Win32MinorVersion = 1) or (Win32MinorVersion = 5) or (Win32MinorVersion = 51)); end;
function GetRunningProcessesIDList(List: TStrings): Boolean; var SnapProcHandle: THandle; ProcEntry: TProcessEntry32; NextProc: Boolean; PIDs: array [0..1024] of DWORD; Needed: DWORD; I: Integer; begin if IsWin3X or IsWinNT4 then begin SnapProcHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); Result := (SnapProcHandle <> INVALID_HANDLE_VALUE);
if Result then try ProcEntry.dwSize := SizeOf(ProcEntry); NextProc := Process32First(SnapProcHandle, ProcEntry); while NextProc do begin List.Add(IntToSTR(ProcEntry.th32ProcessID)); NextProc := Process32Next(SnapProcHandle, ProcEntry); end; finally CloseHandle(SnapProcHandle); end; end else begin Result := EnumProcesses(@PIDs, SizeOf(PIDs), Needed);
if Result then for I := 0 to (Needed div SizeOf(DWORD)) - 1 do List.Add(IntToStR(PIDs[i])); end; end;
function ProcessFileName(PID: DWORD): string; var Handle: THandle; begin Result := ''; Handle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID);
if Handle <> 0 then try SetLength(Result, MAX_PATH);
if GetModuleFileNameEx(Handle, 0, PChar(Result), MAX_PATH) > 0 then SetLength(Result, StrLen(PChar(Result))) else Result := ''; finally CloseHandle(Handle); end; end;
function IsFilePath(ProcessID: DWORD; Path: String): Boolean; var FileName: String; begin case ProcessID of 0: FileName := RsSystemIdleProcess; 2: if IsWinNT4 then FileName := RsSystemProcess else FileName := ProcessFileName(ProcessID); 8: if IsWin2k or IsWinXP then FileName := RsSystemProcess else FileName := ProcessFileName(ProcessID); else FileName := ProcessFileName(ProcessID); end;
Result := UpperCase(FileName) = UpperCase(Path); end;
function GetWindowHandle(ProcessID: DWORD; var Handle: THandle): Boolean;
function EnumerateThreadWindows(Wnd: HWND; Data: lParam): BOOL; begin Handle := Wnd; Result := False; end;
begin Result := EnumThreadWindows(ProcessID, @EnumerateThreadWindows, 0); end;
var LST: TStringList; PID: DWORD; i: Integer; Path: String; WindowHandle: THandle;
LST := TStringList.Create;
if GetRunningProcessesIDList(LST) then begin PID := INVALID_HANDLE_VALUE;
for i := 0 to LST.Count - 1 do if IsFilePath(StrToInt(LST[i]), Path]) then PID := StrToInt(LST[i]);
if PID <> INVALID_HANDLE_VALUE then if GetWindowHandle(PID, WindowHandle) then SendMessage(WindowHandle, WM_CLOSE, 0, 0) end; |
der momentane Code für GetWindowHandle liefert überhaupt keine Ergebnisse, der weggeklammerte hat zwar immer ein paar Fenster zurückgegeben, aber das wahren nie die richtigen! Hab zuerst gedacht, es wären Child-Fenster und dann versucht, mit GetParent an das HauptFenster zu kommen, hat aber auch nicht funktioniert. Wenn man allerdings das ganze 4-5 mal hintereinander ausführt, wird das richtige Fenster gefunden und es klappt so wie es soll, nur das bringt mir an sich nicht sonderlich viel! Weis solangsam nicht mehr was ich machen soll?
Habe es mit mehreren Programmen getestet, scheinbar immer das selbe Problem!
Weis jemand vielleicht, was ich falsch mache, oder geh ich das ganze insgesamt komplett falsch an?
Mit freundlichen Grüßen
Blackbird 8690
_________________ What to do if you find yourself stuck with no hope of rescue. Consider how lucky you are that life has been good to you so far. Alternatively, if life hasn't been good to you so far, consider how lucky you are that it won't be troubling you much longer.
|
|
Regan
      
Beiträge: 2157
Erhaltene Danke: 72
Java (Eclipse), Python (Sublimetext 3)
|
Verfasst: Mi 03.06.09 22:28
Xabitire hat folgendes geschrieben : | Weis jemand vielleicht, was ich falsch mache, oder geh ich das ganze insgesamt komplett falsch an? |
Ob du was falsch machst, kann ich dir nicht beantworten. Ich würde den Weg anders gehen: Erst alle Fenster auflisten ( EnumWinProc), dann kansnt du den Pfad ermitteln, mittels des Wnd-Parameters. Danach noch über GetWindowsLong das Parent bekommen und fertig. Das sollte dir schon erstmal weiterhelfen. Im Endeffekt musst du dir ja immer vor Augen halten, was du willst. Da bringen dir die Prozesse eigentlich gar nichts.
|
|
Xabitire 
      
Beiträge: 114
Win Xp, Win Vista
D6 PE, D7 PE
|
Verfasst: Do 04.06.09 10:29
Wie genau kann ich denn mit Hilfe des Wnd-Parameters den Pfad ermitteln? Diesbezüglich hab ich nämlich nichts gefunden und deshalb auch meinen Ansatz über die Prozesse gestartet!
GetWindowModuleFileName hab ich schon ausprobiert, aber das gibt mir bei jedem Fenster immer nur den Speicherpfad des eigenen Programms zurück!?
_________________ What to do if you find yourself stuck with no hope of rescue. Consider how lucky you are that life has been good to you so far. Alternatively, if life hasn't been good to you so far, consider how lucky you are that it won't be troubling you much longer.
|
|
delphi10
      
Beiträge: 447
Erhaltene Danke: 2
W2K, XP, Vista64, Win7 64
RAD-Studio 2010
|
Verfasst: Do 04.06.09 13:52
Nimm doch einfach folgenden Code
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| Function TFormx.KillTask(ExeFileName: string): Integer; const PROCESS_TERMINATE = $0001; var ContinueLoop: BOOL; FSnapshotHandle: THandle; FProcessEntry32: TProcessEntry32; begin Result := 0; FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); FProcessEntry32.dwSize := SizeOf(FProcessEntry32); ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
while Integer(ContinueLoop) <> 0 do begin if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) = UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) = UpperCase(ExeFileName))) then Result := Integer(TerminateProcess(OpenProcess(PROCESS_TERMINATE,BOOL(0),FProcessEntry32.th32ProcessID), 0)); ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32); end; CloseHandle(FSnapshotHandle); end; |
Du musst nur den Titel des Programmfensters übergeben.
_________________ Salus populi suprema lex esto
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 04.06.09 14:02
delphi10 hat folgendes geschrieben : | Du musst nur den Titel des Programmfensters übergeben. |
Nein, da muss man den Namen der Exe übergeben.
Wozu im Code ganz oben die Prozess-ID ausgelesen wird, verstehe ich sowieso nicht so ganz. Dieser Quelltext ist da besser geeignet, macht aber im Grunde das selbe. Nur dass er nicht den Umweg über die Prozess-ID geht.
|
|
Regan
      
Beiträge: 2157
Erhaltene Danke: 72
Java (Eclipse), Python (Sublimetext 3)
|
Verfasst: Do 04.06.09 15:05
|
|
delphi10
      
Beiträge: 447
Erhaltene Danke: 2
W2K, XP, Vista64, Win7 64
RAD-Studio 2010
|
Verfasst: Do 04.06.09 15:46
_________________ Salus populi suprema lex esto
|
|
Xabitire 
      
Beiträge: 114
Win Xp, Win Vista
D6 PE, D7 PE
|
Verfasst: Do 04.06.09 22:10
So, ich habs jetzt!
Der Fehler war, dass bei der Funktion EnumerateThreadWindows noch zusätzlich ein
Delphi-Quelltext 1:
| export; {$ifdef Win32} stdcall; {$endif} |
dahinter muss! Ansonsten funktioniert das anscheinend nicht!
@jaenicke und delphi10: Ich wollte das Programm eigentlich sauber beenden und nicht "killen"!
@Regan: Das ist ja an sich der selbe Weg wie meiner, nur von der anderen Seiter her angefangen! Allerdings gestaltet sich so die Abfrage ein wenig einfacher, deswegen werde ich es dann sehr wahrscheinlich auch so machen!
Mit freundlichen Grüßen
Felix Klein
_________________ What to do if you find yourself stuck with no hope of rescue. Consider how lucky you are that life has been good to you so far. Alternatively, if life hasn't been good to you so far, consider how lucky you are that it won't be troubling you much longer.
|
|
delphi10
      
Beiträge: 447
Erhaltene Danke: 2
W2K, XP, Vista64, Win7 64
RAD-Studio 2010
|
Verfasst: Do 04.06.09 22:21
Xabitire hat folgendes geschrieben : | So, ich habs jetzt!
@jaenicke und delphi10: Ich wollte das Programm eigentlich sauber beenden und nicht "killen"!
|
Ich hatte mal eine Procedure GetHase geschrieben, ich konnte machen was ich wollte, es kam kein Hase raus;-)
Windows macht nichts anderes, wenn man den Schließmuskel oben rechts anklickt.
_________________ Salus populi suprema lex esto
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 04.06.09 22:25
|
|
delphi10
      
Beiträge: 447
Erhaltene Danke: 2
W2K, XP, Vista64, Win7 64
RAD-Studio 2010
|
Verfasst: Do 04.06.09 23:17
Die DH meint zu TerminateProcess, dass The state of the process object becomes signaled, satisfying any threads that had been waiting for the process to terminate. The process object is deleted when the last handle to the process is closed. Ich hoffe, dass ich nicht zuweit daneben liege.
Das hat auch immer so geklappt, ich sehe darin kein "unsauberes abschiessen oder killen" - genau das macht Windows nach der Abfrage selbst so, alle threads und kind's schließen und danach dann den Mainthread. Verwendet der Prozess aber DLL's, stimmt das so nicht mehr, aber davon war ja auch keine Rede. Hab aber trotzdem eben noch mal versucht eine Situation zu simulieren, in der sich der Process nicht mit dem Close-Button schließen lassen würde, habe ich aber auf die schnelle eben nicht hinbekommen. jaenicke ich weiss aber, wer mir einen Tipp geben könnte 
_________________ Salus populi suprema lex esto
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 04.06.09 23:26
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 05.06.09 00:18
delphi10 hat folgendes geschrieben : | Du musst nur den Titel des Programmfensters übergeben. |
Deswegen heißt der Parameter auch ExeFileName, weil man den Fenstertitel angibt und im Code wird keine einzige Funktion aufgerufen, die irgendwie bezug auf ein Fenster nehmen.
Und bezüglich deiner anderen Aussagen zu TerminateProcess zum Beispiel, lässt mich vermuten, dass du dich entweder nicht richtig inmformiert hast oder nicht weiß, wo von du redest.
|
|
delphi10
      
Beiträge: 447
Erhaltene Danke: 2
W2K, XP, Vista64, Win7 64
RAD-Studio 2010
|
Verfasst: Sa 06.06.09 00:21
Luckie hat folgendes geschrieben : | delphi10 hat folgendes geschrieben : | Du musst nur den Titel des Programmfensters übergeben. |
Deswegen heißt der Parameter auch ExeFileName, weil man den Fenstertitel angibt und im Code wird keine einzige Funktion aufgerufen, die irgendwie bezug auf ein Fenster nehmen.
Und bezüglich deiner anderen Aussagen zu TerminateProcess zum Beispiel, lässt mich vermuten, dass du dich entweder nicht richtig inmformiert hast oder nicht weiß, wo von du redest. |
Das mit dem Übergabenamen hatte ich schon weiter oben aufgeklärt, bzw. erklärt, dass ich mich da vertan hatte. Das man mal danebenliegt, kommt selbstverständlich nur bei mir vor. Jemanden zu unterstellen, er wisse nicht wo von er redet, empfinde ich auch in einem mehr oder weniger anonymen Forum als abwertend.
Wem hast Du mit Deinem kindischen Nachtreten jetzt weitergeholfen? Bin ich Dir irgendwie zu nahe getreten, oder warum pi... Du mich hier öffentlich an? (Das ist nur eine rhetorische Frage auf die ich nicht wirklich eine Antwort erwarte.)Was hast Du außer diesem zitierten posting zur Lösung der Anfangsfrage beigetragen? Zusätzlich bin ich einigermassen irritiert, da Du mir vor einigen Wochen mit einem Tipp zu HardLinks sehr weitergeholfen hast - in einem durch aus polemikfreien Kontext.
Edit: Das war Garf, nicht-wie heißt er gleich nochmal-ach ja, lucki
Im Übrigen bin ich nach wie vor der Ansicht, dass TerminateProcess eine "offizielle" dokumentierte Funktion ist, die nach ihrer Anwendung im Normalfall keinen Programm- oder systemkritischen Zustand hinterlässt - wenn man Ausnahmen (DLL etc.) berücksichtigt, hatte ich aber auch schon oben erwähnt. Was daran ist also "bad", wenn man schnell und unkompliziert ein Problem lösen will? Letztlich ist es eine Frage von Aufwand und Nutzen ob Methoden eingesetzt werden, die alle Spitzfindigkeiten und Eventualitäten abdecken, durch die aber u.U. nach einem halben Jahr keiner mehr durchblickt.
Aber nun isses gut, ich würde es begrüßen, wenn dieser Thread geschlossen würde, da die Lösung ja erabeitet wurde.
_________________ Salus populi suprema lex esto
Zuletzt bearbeitet von delphi10 am Sa 06.06.09 19:12, insgesamt 1-mal bearbeitet
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 06.06.09 00:43
delphi10 hat folgendes geschrieben : | Im Übrigen bin ich nach wie vor der Ansicht, dass TerminateProcess eine "offizielle" dokumentierte Funktion ist, die nach ihrer Anwendung im Normalfall keinen Programm- oder systemkritischen Zustand hinterlässt - wenn man Ausnahmen (DLL etc.) berücksichtigt, hatte ich aber auch schon oben erwähnt. |
Das stimmt nicht, und wenn du in die Dokumentation schaust, wird dort auch davon abgeraten auf diese Weise einen Prozess zu beenden, und das zeigt ja auch schon der obige Text zu TerminateProcess...
Siehe z.B. hier für genauere Informationen: Dokumentation zum Beenden von Prozessen... hat folgendes geschrieben: | [...]
If a process is terminated by TerminateProcess, all threads of the process are terminated immediately with no chance to run additional code. This means that the thread does not execute code in termination handler blocks. In addition, no attached DLLs are notified that the process is detaching. If you need to have one process terminate another process, the following steps provide a better solution:
[...] |
|
|
delphi10
      
Beiträge: 447
Erhaltene Danke: 2
W2K, XP, Vista64, Win7 64
RAD-Studio 2010
|
Verfasst: Sa 06.06.09 01:29
OK, sehe ich jetzt ein. Es gibt doch immer wieder Konstruktionen von denen man felsenfest überzeugt ist. Dabei ist oft noch nicht einmal das absolute Gegenteil richtig. Na gut, hamwa was gelernt, ist doch auch nicht schlecht.
cu del der jetzt dringend schlafen muss phi10
_________________ Salus populi suprema lex esto
|
|
|