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:

Es geht aber auch anders, mit nem Quick&Dirty Trick. Jede laufende Programm startet auch einen Prozess, welcher im Windows-Taskmanager zusehen ist. Dabei vergibt Windows jedem laufendem Prozess eine Prozessidentifikationsnummer (ProcessID), die sich abrufen lässt. Fragt man nach einem Prozess (Anwendung) die nicht aktiv ist, so wird als Ergebnis eine 0 ausgegeben. 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 dem nun 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]