Einzelnen Beitrag anzeigen

RaSoWa1

Registriert seit: 1. Jun 2006
Ort: Halle/Saale
140 Beiträge
 
Delphi 2010 Professional
 
#14

AW: Datei mit Standard-App öffnen und auf Beendigung warten

  Alt 7. Aug 2016, 11:29
Hallo,
ich viel probiert und getestet und verwende jetzt folgenden Code:
Delphi-Quellcode:
function ExecAndWait2(Filename, Params: String; WindowState: Word = SW_SHOWNORMAL): Integer;
const
  cError = -1;
  cWait = 0;
  cNoWait = -2;
var
  ShExecInfoW : SHELLEXECUTEINFOW;
  ExitInfo : PExitThreadDebugInfo;
  wndLstAll,
  wndLst : TStringList;
  i, a : Integer;
  procedure AllProcessToLst(Lst: TStringList);
    function EnumWindowsProcA(Wnd: HWND; LParam: TStringList): BOOL; stdcall;
    begin
      result := True;
      if IsWindowVisible(Wnd) then
      begin
        LParam.Add(IntToStr(Wnd));
      end;
    end;
  begin
    EnumWindows(@EnumWindowsProcA, integer(Lst));
  end;
begin
  Result := cError;
  if (Filename <> '') and FileExists(FileName) then
  begin
    ShExecInfoW.Wnd := GetForegroundWindow;
    ShExecInfoW.cbSize := SizeOf(SHELLEXECUTEINFOW);
    ShExecInfoW.fMask := SEE_MASK_NOCLOSEPROCESS;
    ShExecInfoW.lpVerb := 'open';
    ShExecInfoW.lpFile := PWideChar(WideString(Filename));
    ShExecInfoW.lpParameters := PWideChar(WideString(Params));
    ShExecInfoW.lpDirectory := PWideChar(WideString(ExtractFileDir(Filename)));
    ShExecInfoW.nShow := WindowState;
    wndLstAll := TStringList.Create;
    try
      AllProcessToLst(wndLstAll);
      if ShellExecuteExW(@ShExecInfoW) then
      begin
        result := cNoWait;
        try
          if ShExecInfoW.hProcess <> 0 then
          begin
            WaitForInputIdle(ShExecInfoW.hProcess, INFINITE);
            New(ExitInfo);
            FillChar(ExitInfo.dwExitCode, SizeOf(ExitInfo.dwExitCode), 0);
            repeat
              Application.ProcessMessages;
              sleep(500);
              GetExitCodeProcess(ShExecInfoW.hProcess, ExitInfo.dwExitCode);
            until not(ExitInfo.dwExitCode = STILL_ACTIVE);
            Dispose(ExitInfo);
            Result := cWait;
          end
          else
          // neues Handle ermitteln und auf dessen Beendigung warten:
          begin
            wndLst := TStringList.Create;
            try
              sleep(500); // warten bis App geöffnet ist
              AllProcessToLst(wndLst);
              for i := wndLst.Count - 1 downto 0 do
                if wndLstAll.IndexOf(wndLst[i]) > -1 then
                  wndLst.Delete(i);
              if wndLst.Count > 0 then
               // auf Beendigung warten:
              begin
                repeat
                  Application.ProcessMessages;
                  sleep(500);
                  wndLstAll.Clear;
                  AllProcessToLst(wndLstAll);
                  a := 0;
                  for i := 0 to wndLst.Count - 1 do
                    if wndLstAll.IndexOf(wndLst[i]) > -1 then
                      inc(a);
                until a < wndLst.Count;
                result := cWait;
              end;
            finally
              wndLst.Free
            end;
          end;
        finally
           CloseHandle(ShExecInfoW.hProcess);
        end;
      end;
    finally
      wndLstAll.Free;
    end;
  end;
end;
Die bisherigen Tests auf meinem Rechner liefen alle erfolgreich. Die Funktion wartet immer (auch bei Windows10-Apps) auf deren Beendigung.

Danke an alle Helfer.
Ein schönes Wochenende.
Gruß Klaus.
Klaus
  Mit Zitat antworten Zitat