Tech-Ecke / Delphi Inhalt / Anwendung starten und auf deren Ende warten

 

     Anwendung starten und auf deren Ende warten

Wenn man aus Delphi heraus eine Anwendung startet, so wird der Programmcode nach dem Start mittels ShellExecute munter weitergeführt. Möchte man, dass das Programm anhält bis die Anwendung beendet ist, so gibt es hierfür die Funktionen ShellExecuteAndWait.

  procedure ShellExecAndWait(dateiname, Parameter: string; ShowHide: Integer);   // benötigt ShellAPI in Uses
var executeInfo: TShellExecuteInfo;
dw: DWORD;
begin
   FillChar(executeInfo, SizeOf(executeInfo), 0);
  
with executeInfo do
     
begin
         cbSize := SizeOf(executeInfo);
         fMask := SEE_MASK_NOCLOSEPROCESS
or SEE_MASK_FLAG_DDEWAIT;
         Wnd := GetActiveWindow();
         executeInfo.lpVerb := 'open';
         executeInfo.lpParameters := PChar(Parameter);
         lpFile := PChar(dateiname);
         nShow := ShowHide;
     
end;
     
if ShellExecuteEx(@executeInfo) then dw := executeInfo.HProcess
        
else
            begin

               ShowMessage('Fehler: ' + SysErrorMessage(GetLastError));
               exit;
           
end;
     
while WaitForSingleObject(executeInfo.hProcess, 50) <> WAIT_OBJECT_0 do
      Application.ProcessMessages;
      CloseHandle(dw);
end;

Quelle: http://www.delphipraxis.net

Ausführen:

  ShellExecAndWait('C:\Windows\notepad.exe', '', SW_SHOWNORMAL); // oder SW_HIDE

 

 

Alternative:

Eine weitere Möglichkeit bietet die Prozess-ID. Jedes laufende Programm bekommt von Windows eine eindeutige ID (Integer) zugewiesen, welche man über den Exe-Namen abfragen kann. Fragt man nach einer Anwendung die gerade nicht aktiv ist, so wird eine 0 zurückgegeben.
Hier zunächst mal die Funktion zum auslesen der ProcessID:

  function GetProcessID(Exename: string): DWORD; - benötigt tlhelp32 und  ShellAPI in uses!
var
   hProcSnap: THandle;
   pe32: TProcessEntry32;
begin
   result :=
0;
   hProcSnap := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS,
0);
  
if hProcSnap <> INVALID_HANDLE_VALUE then
     
begin
         pe32.dwSize := SizeOf(ProcessEntry32);
        
if Process32First(hProcSnap, pe32) = true then
            begin
               while Process32Next(hProcSnap, pe32) = true do
                  begin
                    
if pos(Exename, pe32.szExeFile) <> 0 then
                        result := pe32.th32ProcessID;
                   end;
               end;
               CloseHandle(hProcSnap);
   end;
end;

Quelle: http://www.delphipraxis.net

Hat man die oben gezeigt Funktion zum bestimmen der ProcessID in seinem Programm eingebunden, so lässt sich mit folgendem Code das eigene Programm solange anhalten, bis die gestartete Anwendung beendet wurde:

Beispiel: - ShellExecute erfordert ShellAPI in uses!

  var warten: Integer;

ShellExecute(Application.MainForm.Handle,nil,PChar('Anwendung.exe'),nil,nil,SW_HIDE);

repeat
    sleep(
250); // CPU-Entlastung
    application.ProcessMessages;
// halte Fenster aktuell
until GetProcessID('Anwendung.exe') = 0;

 

Hinweis!: Diese Möglichkeit birgt jedoch auch eine Falle. Ist die Anwendung vor dem Start durch das eigene Programm bereits aktiv und wird dadurch zweimal geöffnet, so wird nach dem Schließen der zweiten Anwendung die ProcessID auch nicht 0 sein, da ja noch ein Prozess aktiv ist. Genauso kann es sein, das während des Wartens diese Anwendung ein zweites mal geöffnet wird. Somit währe die ProcessID nach dem schließen der zweiten Anwendung auch nicht 0.
Auch sollte man sich bewusst sein, wenn der Prozess beim Schließen der Anwendung hängen bleibt, so wird auch das Eigene Programm in der Repeat/Until-Schleife hängen bleiben...

 

Die Option Drucken funktioniert erst ab Netscape V4.0 bzw. I-Explorer 5.0 !

[letzte Aktualisierung 01.01.2009]