Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Ferngesteuertes Schließen einer Anwendung (https://www.delphipraxis.net/37767-ferngesteuertes-schliessen-einer-anwendung.html)

PremiumPils 10. Jan 2005 00:11


Ferngesteuertes Schließen einer Anwendung
 
Hallo Leute,

ich hab jetzt leider ien sporadisches Problem, wo ich auf eine Eingebung eurer seits hoffe. Ersteinmal viel Text... aber ich hoffe auf ein oder zwei Hinweise:

Ich habe ein kleines Testprogramm, welches mit Hilfe der Funktion "MyFunktionApplikationIstGestartet(MyHandle,MyEXE) ;" zu einer bestimmten EXE... zum Beispiel "project1.exe" über die Prozessliste das Window-Handle ermittelt. Dieses Handle verwende ich dann in einer Funktion, welche einstellbar lange periodisch versucht m.H. von "PostMessage(MyHandle, WM_CLOSE, 0, 0);" das Programm zu beenden.

Das alles funktioniert prima und anstandlos, wenn da nicht die Ausnahme wäre. Und zwar:

Bei einem Tester ist es so, dass für die zu beendende EXE das Handle richtig ermittelt werden, das Testprogramm also richtig feststellt, dass das zu beendende Programm gestartet ist. Das Programm ist entweder im Hindergrund (hat nicht den Focus - klar, ich hab ja gerade im Testprogramm geklickt) oder ist in der Taskbar minimiert.
Nun wird das Programm jedoch nicht wie bei mir und anderen beendet, sondern bleibt da. Kurios ist aber, dass das Programm beendet wird, wenn der Tester während der priodischen Versuche dem zu beendenden Programm den Focus gibt.

:wall: Ich steh auf dem Schlauch, und weiß nicht, wie ich dem zu beendenden Programm auf die Sprünge helfen kann!? Focus geben? Automatisch? Empfängt es die Nachricht ohen Focus? Help...

Euer
PremiumPils

Sprint 10. Jan 2005 00:22

Re: Ferngesteuertes Schließen einer Anwendung
 
Zitat:

Zitat von PremiumPils
welche einstellbar lange periodisch versucht m.H. von "PostMessage(MyHandle, WM_CLOSE, 0, 0);" das Programm zu beenden.

Delphi-Quellcode:
SendMessage(MyHandle, WM_SYSCOMMAND, SC_CLOSE, 0);
Warum periodisch?

PremiumPils 10. Jan 2005 01:03

Re: Ferngesteuertes Schließen einer Anwendung
 
Zitat:

Warum periodisch?
Hi, danke für die rasche Antwort, werd ich gleich mal ausprobieren - kurz bevor ich ruhen gehe.

Periodisch, weil das zu beendende Programm, nunja, wie schon angemerkt störisch ist. Und wenn es mehrere Fenster offen hat, hat dieses auch schon geholfen. Aber im Grunde hat sich dies daraus ergeben, da das Programm oftmals zwischen 5-20 Sekunden (je nach Datenvolumen) benötigt, um sich selber zu schließen. So lange wartet mein Programm - in der Zeit schick ich halt die Nachrichten raus.

Grüße,
PremiumPils

PremiumPils 10. Jan 2005 16:23

Re: Ferngesteuertes Schließen einer Anwendung
 
Die andere Procedure schließt bei mir zwar auch das Programm, jedoch beim "Sorgenkind".. der Ausnahme nicht. Gibt es eine andere Lösung, oder kennt jemand spezielle Rahmenbedingungen auf einem Win2000 System, die diese Nachrichten an das zu schließende Programm behindern?

Sprint 10. Jan 2005 16:49

Re: Ferngesteuertes Schließen einer Anwendung
 
Zitat:

Zitat von PremiumPils
Die andere Procedure schließt bei mir zwar auch das Programm, jedoch beim "Sorgenkind".. der Ausnahme nicht. Gibt es eine andere Lösung, oder kennt jemand spezielle Rahmenbedingungen auf einem Win2000 System, die diese Nachrichten an das zu schließende Programm behindern?

Kannst du die Anwendung über den "X" Button im Fenster schließen? Wenn ja, dann hast du das falsche Fensterhandle.

PremiumPils 10. Jan 2005 18:54

Re: Ferngesteuertes Schließen einer Anwendung
 
Okay, also ich konnte jetzt was eingrenzen:

-den Wert in der INI auf 20 Sekunden stellen
-XYZ starten, wenn schon nicht
-mein Programm starten
-Auto Beenden = an
-Update starten, nun sollte XYZ ja beenden werden
-nun gleich mal XYZ den Fokus geben, also auf die Taskbar oder den Tray-Eintrag drücken

Antwort:
19:51 Bernd: XYZ is minimiert, wird nich beendet
19:51 Bernd: XYZ is im hintergrund maximiert ohne focus, wird beendet

Dieses verhalten wurde nun auch von jemanden anderes bestätigt. Nun gleich meine Frage, wie schicke ich an einen bestimmten Prozess, welcher gerade wohl kein Fenster hat (?!) eine Nachricht, das er beendet wird? Und wie stelle ich fest, ob der Prozess - eine bestimmte EXE gestartet ist?

verzweifelnd über sein unwissen,
PremiumPils

Sprint 10. Jan 2005 22:16

Re: Ferngesteuertes Schließen einer Anwendung
 
Zitat:

Zitat von PremiumPils
wie schicke ich an einen bestimmten Prozess, welcher gerade wohl kein Fenster hat (?!) eine Nachricht, das er beendet wird?

In dem du eine WM_QUIT Nachricht an den Thread schickst. Wie beendet man das Programm als Benutzer?

Zitat:

Und wie stelle ich fest, ob der Prozess - eine bestimmte EXE gestartet ist?
In dem du von jedem Prozess die Parent ProcessID mit dem Programm vergleichst.

PremiumPils 10. Jan 2005 22:43

Re: Ferngesteuertes Schließen einer Anwendung
 
Zitat:

In dem du eine WM_QUIT Nachricht an den Thread schickst.
Beendet WM_QUIT, oder schließt es. Sprich, kommt der Thread noch dazu, seine Daten zu speichern?

Zitat:

Wie beendet man das Programm als Benutzer?
Ja - normal halt, da es sich um ein normales Delphi Windows Programm handelt, welches, wenn man es ins Tray minimiert im Task-Manager aus der Anwendungen-Liste verschwindet, und nur noch in der Prozesse-Liste ist. Dann funktioniert es wohl nicht mehr wie es soll.

Der Benutzer kann das Programm+zugehöriges Fenster mit einem klick auf das Tray-Icon wiederherstellen. Dann einfach nur noch auf das X im System Menu oben drücken, und es ist auch beendet.

Anbei einmal die beiden Funktionen, wie ich sie ursprünglich benutze:

Delphi-Quellcode:
function OwnFunctionAppKill2(MyEXE : string; MyWarteZeit:Integer) : boolean;
var
  MyHandle : HWND;
  MyZaehler : Integer;
begin
  Result := false;
  if OwnFunctionAppIsRunning2(MyHandle,MyEXE) then
  begin
    for MyZaehler := 1 to (MyWarteZeit * 4) do
    begin
      Sleep(250);
      Application.ProcessMessages;
      if not OwnFunctionAppIsRunning2(MyHandle,MyEXE) then
      begin
        Result := true;
        break;
      end
      else
      begin
        Result := false;
        PostMessage(MyHandle, WM_CLOSE, 0, 0);
      end;
    end;
  end
  else
  begin
    Result := true;
  end;
end;
{--------------------------------------------------------------------------------------------------------------}
{--------------------------------------------------------------------------------------------------------------}
function OwnFunctionAppIsRunning2(var MyHandle : HWND; MyEXE : String) : Boolean;
  function GetWindowByAppName(ApplicationName: String): Cardinal;
    function GetAppProcID(ApplicationName : String):Cardinal;
    var
      bContinue: BOOL;
      aSnapshotHandle: THandle;
      aProcessEntry32: TProcessEntry32;
    begin
      result := 0;
      aSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
      aProcessEntry32.dwSize := SizeOf(aProcessEntry32);
      bContinue := Process32First(aSnapshotHandle, aProcessEntry32);
      while Integer(bContinue) <> 0 do
      begin
        if LowerCase(aProcessEntry32.szExeFile) = LowerCase(ApplicationName) then result := aProcessEntry32.th32ProcessID;
        bContinue := Process32Next(aSnapshotHandle, aProcessEntry32);
      end;
      CloseHandle(aSnapshotHandle);
    end;
    function GetHandleFromProcID(aProcID : Cardinal) : Cardinal;
       function EnumWindowsProc(hWnd: HWND; lParam: LPARAM): BOOL; stdcall;
       begin
         TList(lParam).Add(Pointer(hWnd));
         Result := True;
       end;
    var
      List: TList;
      ProcessId: DWORD;
      I: Integer;
    begin
      Result := 0;
      List := TList.Create;
      try
        if EnumWindows(@EnumWindowsProc, Longint(List)) then
        begin
          for I := 0 to List.Count - 1 do
          begin
            GetWindowThreadProcessId(Longint(List.Items[I]), ProcessId);
            if aProcID = ProcessId then
            begin
              Result := Longint(List.Items[I]);
              Break;
            end;
          end;
        end;
      finally
        List.Free;
      end;
    end;
  begin
    result := GetHandleFromProcID(GetAppProcID(ApplicationName));
  end;
begin
  MyHandle := GetWindowByAppName(MyEXE);
  if (MyHandle <> 0 ) then Result := true
                      else Result := false;
end;

Sprint 11. Jan 2005 00:21

Re: Ferngesteuertes Schließen einer Anwendung
 
Zitat:

Zitat von PremiumPils
Delphi-Quellcode:
PostMessage(MyHandle, WM_CLOSE, 0, 0);

Laß dir doch in einer MessageBox das Fensterhandle und den Titel anzeigen. Dann kannst du die Werte ja mal mit Spy++, WinSpy oder X-Spy vergleichen. Vielleicht hast du ein Fenster der Anwendung, aber nicht das richtige.

Zitat:

Zitat von PremiumPils
Delphi-Quellcode:
if LowerCase(aProcessEntry32.szExeFile) = LowerCase(ApplicationName) then result := aProcessEntry32.th32ProcessID;

Unter Windows 2000/XP/2003 steht dort nur der Dateiname drin. Unter Windows 9x steht in szExeFile der vollständige Dateiname drin.

Windows 2k/XP/2k3: NOTEPAD.EXE

Windowx 9x: C:\WINDOWS\NOTEPAD.EXE

PremiumPils 12. Jan 2005 18:26

Re: Ferngesteuertes Schließen einer Anwendung
 
Hallo, vielen Dank für Deine Hilfe. Ich hab das Problem nun eingrenzen und zu guter letzt auch lösen können. Es lag mehr oder weniger mit dem zu beendenden Programm zusammen, welches mal nur als Prozess in der Tray, mal minimiert in der Taskleiste und mal als Fenster da ist.. und mal überall. :) Toi toi toi... es geht nun. :gruebel:

Ganz nebenbei hab ich noch einen "Ungültiges Fensterhandle: 1400" und ein "Fehler beim Erstellen des Fenster-Gerätekontexts."-Fehler behoben. :roll:


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:56 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