Wait before ShellExecute is carried out?

后端 未结 3 1045
我在风中等你
我在风中等你 2021-02-15 03:54

I have a hopefully quick question: Is it possible to delay execution of ShellExecute a little bit?

I have an application with autoupdater. After it downloads all necess

相关标签:
3条回答
  • 2021-02-15 04:43

    You're doing an autopatcher right ?

    I've had the same problem and this is how I bypassed it :

    You run second app with argument "--delay" or something like that. Second app handles argument "--delay" and sleeps for 100 ms, then continues running normally.

    0 讨论(0)
  • 2021-02-15 04:45

    This routine is some utils code in our game engine. It can run an executable and optionally wait for it to exit. It will return its exit code:

    function TSvUtils.FileExecute(ahWnd: Cardinal; const aFileName, aParams, aStartDir: string; aShowCmd: Integer; aWait: Boolean): Integer;
    var
      Info: TShellExecuteInfo;
      ExitCode: DWORD;
    begin
    
      Result := -1;
      FillChar(Info, SizeOf(Info), 0);
      Info.cbSize := SizeOf(TShellExecuteInfo);
      with Info do begin
        fMask := SEE_MASK_NOCLOSEPROCESS;
        Wnd := ahWnd;
        lpFile := PChar(aFileName);
        lpParameters := PChar(aParams);
        lpDirectory := PChar(aStartDir);
        nShow := aShowCmd;
      end;
    
      if ShellExecuteEx(@Info) then
      begin
        if aWait then
        begin
          repeat
            Sleep(1);
            Application.ProcessMessages;
            GetExitCodeProcess(Info.hProcess, ExitCode);
          until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
          CloseHandle(Info.hProcess);
          Result := ExitCode;
        end;
      end
    end;
    

    Here is some code that can check to see if a process exists. So... current app calls the updater and terminates. The updater can check to see if old app has terminated and do it's thing (rename, update, delete, etc):

    function TSvUtils.ProcessExists(const aExeFileName: string; aBringToForgound: Boolean=False): Boolean;
    var
      ContinueLoop: BOOL;
      FSnapshotHandle: THandle;
      FProcessEntry32: TProcessEntry32;
    begin
    
      FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
      FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
      ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
      Result := False;
      while Integer(ContinueLoop) <> 0 do
      begin
        if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
          UpperCase(aExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) =
          UpperCase(aExeFileName))) then
        begin
          if aBringToForgound then
            EnumWindows(@BringToForgroundEnumProcess, FProcessEntry32.th32ProcessID);
          Result := True;
        end;
        ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
      end;
      CloseHandle(FSnapshotHandle);
    end;
    
    0 讨论(0)
  • 2021-02-15 04:48

    If you can use CreateProcess instead of ShellExecute, you can wait on the process handle. The process handle is signalled when the application exits. For example:

    function ExecAndWait(APath: string; var VProcessResult: cardinal): boolean;
    var
      LWaitResult : integer;
      LStartupInfo: TStartupInfo;
      LProcessInfo: TProcessInformation;
    begin
      Result := False;
    
      FillChar(LStartupInfo, SizeOf(TStartupInfo), 0);
    
      with LStartupInfo do
      begin
        cb := SizeOf(TStartupInfo);
    
        dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
        wShowWindow := SW_SHOWDEFAULT;
      end;
    
      if CreateProcess(nil, PChar(APath), nil, nil, 
                       False, NORMAL_PRIORITY_CLASS,
                       nil, nil, LStartupInfo, LProcessInfo) then
      begin
    
        repeat
          LWaitResult := WaitForSingleObject(LProcessInfo.hProcess, 500);
          // do something, like update a GUI or call Application.ProcessMessages
        until LWaitResult <> WAIT_TIMEOUT;
        result := LWaitResult = WAIT_OBJECT_0;
        GetExitCodeProcess(LProcessInfo.hProcess, VProcessResult);
        CloseHandle(LProcessInfo.hProcess);
        CloseHandle(LProcessInfo.hThread);
      end;
    end;
    

    After ExecAndWait returns, then you can sleep for 100ms if you need to.

    N@

    0 讨论(0)
提交回复
热议问题