auf Beendigung von externer Anwendung warten

Supa

Erfahrenes Mitglied
Hy,

ich schreibe eine Anwendung (Anw1), aus der herraus ich eine zweite Anwendung(Anw2) starte.

Wie kann ich jetzt aus meiner ersten Anwendung herraus feststellen, ob die zweite Anwendung beendet wurde?

Meine Idee war ja, Anw2 mit ShellExecute(...) zu starten. Dann hätt ich ein Handle zu der Anwendung. Aber irgendwie kann ich nicht vernünftig mit dem Handel umgehn.

Eine andere Idee war, in Anw1 in ner while-Schleife FindWindow(NULL,"Anw2-Fenstername") abzufragen. Das funktioniert auch, aber das is ja nu nicht die feine englische Art, zumal meine Anw1 dann in ner Schleife festhängt.

mfg
 
Hallo,

Du kannst doch die while schleife in einem extra Timer laufen lassen, dann hängt dein Programm nicht.

Ich hab das prüfen einer externen Anwendung so gemacht:
Ich starte mein Programm aber mit CreateProcess und nicht mit ShellExecute

C++:
PROCESS_INFORMATION pi1;
std::string strCmdline= "MeinProgramm.exe";
...

if(!CreateProcess(  NULL,       // No module name (use command line)
               szCmdline,       // Command line
               NULL,            // Process handle not inheritable
               NULL,            // Thread handle not inheritable
               FALSE,           // Set handle inheritance to FALSE
               0,               // No creation flags
               NULL,            // Use parent's environment block
               NULL,            // Use parent's starting directory
               &si1,            // Pointer to STARTUPINFO structure
               &pi1 )           // Pointer to PROCESS_INFORMATION structure
          )
          {
               AnsiString tmp = "CreateProcess failed (";
               tmp += GetLastError();
               tmp += ")";
               ShowMessage(tmp);
          }

Für das Prüfen ob das Programm noch lebt merkst du dir das pi1 (Process Information)

C++:
if (WaitForSingleObject(pi1.hProcess, 1) != WAIT_TIMEOUT)
{
            //läuft nicht mehr
            //Prozesshandle gilt als gesetzt, wenn es nicht mehr existiert 
}
dieses if(WaitFor....) hab ich auch in einem extra Timer am laufen.

MfG Turri
 
Okay, danke...

Man, jetzt hatte ich hier gerade ne ellenlange Antwort verfasst, da stürzt das Forum ab :mad:

Naja... jedenfalls hab ich das Problem mit dem festhängen in der Schleife jetzt mit der Auslagerung in einen eigenen Thread gelöst. Funktioniert soweit auch ganz gut.

Das Programm das ich gerade schreibe soll nun als Startbildschirm dienen. Von dort aus starte ich eine zweite Anwendung und damit der User während des Starts der zweiten Anwendung (ca. 4Sekunden) nicht im dunkeln tappt und womöglich weitere male auf das Start-Icon klickt, soll halt während dessen der Startbildschirm angezeit werden. Geht soweit auch alles schon.

Das Problem vor dem ich nun stehe ist einfach, dass ich nicht weiß, wann die zweite Anwendung fertig gestartet ist, um den Startbildschirm zu beenden. Zuerst wollte ich in der fertig gestarteten Anwendung eine Funktion like:
Code:
BOOL CloseWindow(
    HWND hWnd
   );
, aufrufen. Leider minimiert diese den Startbildschirm aber nur. Und DestroyWindow() funktioniert einfach nicht. Ich denke das hat was mit der Sicherheit zu tun.

Mein zweiter Ansatz ist nun, das ich aus der fertig gestarteten Anwendung eine Art Nachricht an den Startbildschirm schicke und dieser sich darauf hin beendet. Ich dachte da jetzt an Funktionen wie SendMessage(...) und GetMessage(...). Nur weis ich nicht, wie ich diese richtig verwende bzw. ob das überhaupt damit geht...

Kann mir da jemand weiter helfen?

mfg
 
Hallo,

Du kannst Anwendungen mit
C++:
PostMessage(hwnd,WM_CLOSE,0,0);
beenden. Wenn du das entsprechende HWND hast, alles kein Problem.
Der Befehl klotzt dir eigentlich jede Anwedung weg, habs noch nie erlebt das der nicht geht :)

Zum Prüfen ob eine Anwendung komplett geladen ist, hab ich auch nur eine seltsame Lösung weil bei mir OnCreate beim Form1 auch nicht langte. Ich hab mir einen "Hilfstimer" auf das Form gelegt. Der steht standardmäßig auf "enabled". Der macht bei mir nur einen Durchlauf und der der Intervall steht auf 1/1000 Sekunde. Und wenn der Timer losrennt, dann weiß ich das meine Anwendung komplett geladen ist. Dadurch das der Timer erst losrennt wenn das Form sichtbar ist, hat der Nutzer eine "visuelle" Rückmeldung das was neues da ist, und klickert nicht dumm rum ;-)

Wer dafür ne bessere Lösung hat, die würde ich auch gern hören :)

MfG Turri
 
Zuletzt bearbeitet:
Ich hätte ja noch nen dritten Ansatz gehabt. Einfach ne Datei auf die Platte schreiben wenn die Anwendung fertig geladen (OnShow()) ist.
Code:
FileCreate("geladen.tmp");
und in der anderen Anwendung einfach in nem Thread in einer While-Schleife:
Code:
while(!FileExists("geladen.tmp"))
{
   //hier rein, was passiert, wenn die Anwendung noch nicht fertig geladen ist
   //z.b. den Fortschritt bei nem Ladebalken verändern
}
//das mit dem löschen von Dateien, 
//die eine andere Anwendung erzeugt hat, 
//die noch nicht beendet ist macht bei mir allerdings noch probleme
DeleteFile("geladen.tmp")

Okay, zu deiner Antwort. Das mit PostMessage() funktioniert!

Aber irgendwie is das immernoch nicht das gewünschte Ergebniss. Besser wäre, wenn ich eine benutzerdefinierte Message (oder wenigstens eine Message, die ich abfangen kann) zum Starbildschirm schicken könnte, damit er selbst beenden kann. Vor dem beenden muss er nämlich noch etwas erledigen (z.B. ausblenden), sonst sieht's so abgehackt aus, wenn der Startbildschirm einfach verschwindet.

Wie schon gesagt, ich könnt mir vorstellen, dass das mit Send-/ und GetMessage() funktionieren könnte. Ich hab nur noch nicht raus, wie....

Also: weiterhin offen für Vorschläge! ;)
 
Ich nochmal...

hab's jetzt erstmal anders gelöst:
die startende Anwendung ruft, wenn fertig geladen:
Code:
PostMessage(FindWindow(0,"Startbildschirm"),WM_CLOSE,0,0);
auf.

Im Startbildschirm-Programm wird dann das Ereigniss OnCloseQuery() aufgerufen welches im ersten Versuch geblock bzw. verhindert wird. Die Routine, welche das Externe Programm gestartet hat, kommt aus der Schleife raus (abfrage, ob OnCloseQuery schon einmal afgerufen wurde), blendet den Bildschirm aus, und schließt ihn letztendlich im zweiten Versuch, welche in dem OnCloseQuery() Ereigniss nicht mehr geblockt wird.

tataaaa... ist wahrscheinlich immernoch nicht perfekt, aber so geht's erstmal bis ich mehr weiß.

MfG & danke für die Antworten ;)
 
Zurück