Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi Programm starten u. auf dessen Ende warten + Rückgabewert (https://www.delphipraxis.net/137061-programm-starten-u-auf-dessen-ende-warten-rueckgabewert.html)

Andreas L. 13. Jul 2009 17:04


Programm starten u. auf dessen Ende warten + Rückgabewert
 
Manchmal ist es nötig von einem gestarteten Programm eine Antwort zu erhalten. Z. B. hat man ein Update-Programm und möchte wissen ob eine neue Version verfügbar ist oder das Update erfolgreich installiert wurde. Dazu kann man den ExitCode der Anwendung setzen. ExitCode ist eine Integer-Variable. Zur besseren Code-Lesbarkeit können wir uns noch einen eigenen Typen in den beiden Anwendungen definieren. Z. B.
Delphi-Quellcode:
  type
    TUpdateResult = (urSuccessful, urError);
In der zu startenden Anwendung (Update.exe) einfach im z. B. OnClose des MainForms oder nach ausführen einer Aktion:
Delphi-Quellcode:
  //globale Variable
  var
    MyUpdateResult: TUpdateResult;

...
...
  //Bsp.: Eine Datei kopieren und bei Erfolg den Wert
  //urSuccessful unserer globalen Variable zuweisen
  if CopyFile('Datei.exe', 'Datei.exe', False) then
    MyUpdateResult := urSuccessful
  else
    MyUpdateResult := urError;

...
...
  //Den Wert aus unserer Variable nach Integer casten und in die Variable ExitCode eintragen
  ExitCode := Integer(MyUpdateResult);
In der Hauptanwendung welche das Update z. B. bei einem ButtonClick startet, müssen wir uns nur noch TShellExecuteInfo, ShellExecuteEx, GetExitCodeProcess und WaitForSingleObject bedienen:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
   ExecuteInfo: TShellExecuteInfo;
   UpdateResult: TUpdateResult;
   Temp: Integer;
begin
  //Einstellungen setzen
  FillChar(ExecuteInfo, SizeOf(ExecuteInfo), 0);
  ExecuteInfo.cbSize := SizeOf(TShellExecuteInfo);
  with ExecuteInfo do
  begin
    fMask := SEE_MASK_NOCLOSEPROCESS;
    wnd := Application.Handle;

    //Auszuführende Anwendung
    lpFile := PChar('Update.exe');

    //auf Wunsch noch Parameter mitgeben
    //lpParameters := PChar('-EinParameter');

    //Wenn Update.exe im selben Verzeichnis wie die Hauptanwendung liegt, ansonsten anpassen!
    lpDirectory := PChar(ExtractFilePath(Application.ExeName));

    //Update.exe anzeigen, weitere Möglichkeiten SW_HIDE oder SW_MAXIMIZED, etc.
    nShow := SW_SHOWNORMAL;
  end;

  //Anwendung starten
  if not ShellExecuteEx(@ExecuteInfo) then
    RaiseLastOSError;

  //Warten bis Update.exe beendet wird, anstatt INFINITE kann man auch eine
  //Wartezeit in Milisekunden übergeben z. B. 120000 für 2 Min.
  WaitForSingleObject(ExecuteInfo.hProcess, INFINITE);

  //ExitCode holen
  GetExitCodeProcess(ExecuteInfo.hProcess, TempCode);

  //Handle schließen
  CloseHandle(ExecuteInfo.hProcess)

  //Nach TUpdateResult casten...
  UpdateResult := TUpdateResult(TempCode);

  //...und auswerten
  case UpdateResult of
    urError: ShowMessage('Es ist ein unbekannter Fehler aufgetreten!'); //Wie ich diese Fehlermeldung liebe ;-)
    urSuccessful: ShowMessage('Update wurde installiert :-)');
  end;

end;

Apollonius 13. Jul 2009 17:09

Re: Programm starten u. auf dessen Ende warten + Rückgabewer
 
Da leckt ein Handle. ;-) CloseHandle(ExecuteInfo.hProcess) fehlt. Außerdem sollte man die Rückgabewerte auswerten und ggf. eine passende Exception werfen. Daneben ist es Konvention, dass der ExitCode Null für Erfolg und alles andere für einen Fehler steht; bei dir ist es andersherum.

Andreas L. 13. Jul 2009 17:31

Re: Programm starten u. auf dessen Ende warten + Rückgabewer
 
Zitat:

Zitat von Apollonius
Da leckt ein Handle. ;-) CloseHandle(ExecuteInfo.hProcess) fehlt. ... Daneben ist es Konvention, dass der ExitCode Null für Erfolg und alles andere für einen Fehler steht; bei dir ist es andersherum.

Habs geändert, danke für den Hinweis :thumb:

Zitat:

Außerdem sollte man die Rückgabewerte auswerten und ggf. eine passende Exception werfen.
Wo genau bzw. welche Rückgabewerte soll ich auswerten?

Apollonius 13. Jul 2009 17:38

Re: Programm starten u. auf dessen Ende warten + Rückgabewer
 
Insbesondere bei ShellExecuteEx solltest du auf Fehler prüfen. Sonst kann eigentlich nicht viel schiefgehen.

Andreas L. 13. Jul 2009 17:44

Re: Programm starten u. auf dessen Ende warten + Rückgabewer
 
Zitat:

Zitat von Apollonius
Insbesondere bei ShellExecuteEx solltest du auf Fehler prüfen. Sonst kann eigentlich nicht viel schiefgehen.

Bin mir nicht sicher welche Exception ich auslösen soll, wie wärs damit:

Delphi-Quellcode:
  //Anwendung starten
  if not ShellExecuteEx(@ExecuteInfo) then
    raise Exception.Create('ERROR:' + IntToStr(GetLastError));

Apollonius 13. Jul 2009 17:51

Re: Programm starten u. auf dessen Ende warten + Rückgabewer
 
Du kannst einfach die Routine RaiseLastOSError verwenden.

Andreas L. 13. Jul 2009 17:53

Re: Programm starten u. auf dessen Ende warten + Rückgabewer
 
Zitat:

Zitat von Apollonius
Du kannst einfach die Routine RaiseLastOSError verwenden.

Klar, hätt' ich auch selber drauf kommen müssen :oops:

Habs eingebaut 8)

nachtstreuner 27. Apr 2012 09:45

AW: Programm starten u. auf dessen Ende warten + Rückgabewert
 
Hallo Andreas, hallo Apollonius,

vielen Dank für Eure Beiträge. Die Erklärungen tragen leider nichts zur Lösung meines Problems bei, sind aber sehr interessant und im Code mit Sicherheit zu berücksichtigen. Werde ich auch testen.

Nach langem Probieren, warum die Packliste(@backup.lst) nicht ausgelesen wurde, habe ich nun die vermeintliche Lösung gefunden.

Ich mache noch ein paar Tests in Bezug auf Leerzeichen, Sonderzeichen in Dateinamen und werde das Ergebnis posten bzw.
wenn gewünscht werde ich versuchen, wenn nun alles sauber funktioniert ein aussagekräftiges Tut. zu schreiben, für alle die sich mit den Kommandozeilen in der RAR.exe herumschlagen wollen.

Beim jetzigen Test, werden sowohl ganze Ordner mit Unterordner , sowie Dateien mit RAR aus Delphi heraus gepackt. Wunschweise auch mit Ursprungspfad oder auch Ohne (siehe param -ep1).

Wie gesagt ich melde mich gleich wieder.

Gruß nachtstreuner


Alle Zeitangaben in WEZ +2. Es ist jetzt 23:03 Uhr.

Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf