如何正确使用WaitForSingleObject方法等待外部程序终止?

时间:2011-03-10 14:35:49

标签: delphi delphi-2007

我正在尝试启动具有提升状态的外部应用程序,并等到它退出后再继续:

var
  FProcess: THandle;
  ExecInfo: TShellExecuteInfo;
begin

  FillChar(ExecInfo, SizeOf(ExecInfo), 0);
  with ExecInfo do
  begin
    cbSize := SizeOf(ExecInfo);
    fMask := 0;
    Wnd := AWindow;
    lpVerb := 'runas';
    lpFile := PChar(APath);
    lpParameters := PChar(AParams);
    lpDirectory := PChar(AWorkDir);
    nShow := SW_NORMAL;
  end;

  Result := ShellExecuteEx(@ExecInfo);

  if Wait then
  begin
    while WaitForSingleObject(ExecInfo.hProcess, INFINITE) <> WAIT_TIMEOUT do
      Application.ProcessMessages;
  end;

这启动了,但它一直在等待。即使在被调用的程序退出之后,调用程序也永远不会继续调用WaitForSingleObject。

我尝试过WAIT_OBJECT_0而不是WAIT_TIMEOUT,但我遇到了同样的问题。我在这里做错了什么?

3 个答案:

答案 0 :(得分:11)

代码是什么

while WaitForSingleObject(ExecInfo.hProcess, INFINITE) <> WAIT_TIMEOUT do
  Application.ProcessMessages;

该怎么办?这是一个无限循环。

仅使用

WaitForSingleObject(ExecInfo.hProcess, INFINITE);

代替。是的,你需要

fMask:= SEE_MASK_NOCLOSEPROCESS;

获取进程句柄。

答案 1 :(得分:4)

您的代码已损坏。您没有将SEE_MASK_NOCLOSEPROCESS标记传递给ShellExecuteEx(),因此它不会向您返回有效的流程句柄,并且您的循环忽略了WaitForSingleObject()因此而告诉您的错误,因此你最终会陷入无休止的循环中。

请改为尝试:

var
  ExecInfo: TShellExecuteInfo;
begin
  ZeroMemory(@ExecInfo, SizeOf(ExecInfo));
  with ExecInfo do
  begin
    cbSize := SizeOf(ExecInfo);
    fMask := SEE_MASK_NOCLOSEPROCESS;
    Wnd := AWindow;
    lpVerb := 'runas';
    lpFile := PChar(APath);
    lpParameters := PChar(AParams);
    lpDirectory := PChar(AWorkDir);
    nShow := SW_NORMAL;
  end;
  Result := ShellExecuteEx(@ExecInfo);
  if Result and Wait then
  begin
    if ExecInfo.hProcess <> 0 then // no handle if the process was activated by DDE
    begin
      repeat
        if MsgWaitForMultipleObjects(1, ExecInfo.hProcess, FALSE, INFINITE, QS_ALLINPUT) = (WAIT_OBJECT_0+1) then
          Application.ProcessMessages
        else
          Break;
      until False;
      CloseHandle(ExecInfo.hProcess);
    end;
  end; 
end;

答案 2 :(得分:2)

如果您阅读description of ShellExecuteEx in MSDN,您会看到:

  

hProcess

Type: HANDLE
     

新启动的应用程序的句柄。此成员已开启   除非fMask,否则返回并始终为NULL   设置为SEE_MASK_NOCLOSEPROCESS。   即使fMask设置为   SEE_MASK_NOCLOSEPROCESS,hProcess将   如果没有启动进程,则为NULL。

即。你根本没有有效的句柄。您需要如上所述设置fMask。