Autor Beitrag
Andreas L.
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1703
Erhaltene Danke: 25

Windows Vista / Windows 10
Delphi 2009 Pro (JVCL, DragDrop, rmKlever, ICS, EmbeddedWB, DEC, Indy)
BeitragVerfasst: Mo 13.07.09 16:53 
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.
ausblenden Delphi-Quelltext
1:
2:
  type
    TUpdateResult = (urSuccessful, urError);


In der zu startenden Anwendung (Update.exe) einfach im z. B. OnClose des MainForms oder nach ausführen einer Aktion:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
  //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:
ausblenden volle Höhe 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:
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:
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;