等待ShellExecute执行之前?

时间:2011-05-15 16:20:12

标签: delphi delay shellexecute

我有一个希望很快的问题:是否有可能延迟执行ShellExecute一点?

我有一个autoupdater应用程序。在下载所有必需的文件等之后,它会将当前文件重命名为* .OLD,将新文件重命名为之前的文件。很简单。但后来我需要删除那些.OLD文件。这个'清理'程序在MainForm.OnActivate上执行(检查它是否是第一个激活proc)。但这显然发生得太快(我从DeleteFile得到False)。这是程序:

procedure TUpdateForm.OKBtnClick(Sender: TObject);
const SHELL = 'ping 127.0.0.1 -n 2';
begin
  ShellExecute(0,'open',pchar(SHELL+#13+Application.ExeName),nil,nil,SW_SHOWNORMAL);
  Application.Terminate;
end;

此过程应该重新启动应用程序。我确定删除问题是由第二个应用程序的快速启动引起的,因为如果我自己重新启动它,给它一点时间,文件会被正常删除。

tl; dr 版本:我需要调用ShellExecute()等待一段时间(0.1秒左右),然后THEN执行命令。

注意

我尝试使用-ping命令尝试延迟它,但它没有用。

非常感谢您提前

修改:改写

我需要这个发生|| 第一个应用关闭;等待100毫秒;第二个应用程序打开 ||。我需要先调用ShellExecute,然后等待调用应用程序完全关闭,然后执行shell(即打开第二个应用程序)

3 个答案:

答案 0 :(得分:5)

你正在做自动检查吗?

我遇到了同样的问题,这就是我绕过它的方式:

您使用参数“--delay”运行第二个应用程序或类似的东西。 第二个应用处理参数“--delay”并休眠100毫秒,然后继续正常运行。

答案 1 :(得分:3)

这个例程是我们游戏引擎中的一些utils代码。它可以运行可执行文件并可选择等待它退出。它将返回其退出代码:

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;

以下是一些可以检查进程是否存在的代码。所以...当前应用程序调用更新程序并终止。更新程序可以检查旧应用程序是否已终止并执行此操作(重命名,更新,删除等):

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;

答案 2 :(得分:2)

如果您可以使用CreateProcess而不是ShellExecute,则可以等待进程句柄。应用程序退出时会发出进程句柄信号。例如:

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;

ExecAndWait返回后,如果需要,你可以睡100ms。

N - [

相关问题