How do I properly use the WaitForSingleObject method to wait for an external program to terminate?

croceldon picture croceldon · Mar 10, 2011 · Viewed 19.1k times · Source

I'm trying to launch an external application with elevated status, and wait until it exits before continuing:

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;

This launches, but it just keeps waiting. The calling program never continues past the call to WaitForSingleObject, even after the called program exits.

I've tried WAIT_OBJECT_0 instead of WAIT_TIMEOUT, but I have the same problem. What am I doing wrong here?

Answer

kludg picture kludg · Mar 10, 2011

What the code

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

is supposed to do? It is an infinite loop.

Use just

WaitForSingleObject(ExecInfo.hProcess, INFINITE);

instead. And yes, you need

fMask:= SEE_MASK_NOCLOSEPROCESS;

to obtain the process handle.