从管道读取时的ReadFile阻塞

时间:2015-01-24 18:13:40

标签: delphi winapi

我想读一个控制台程序输出。问题是ReadFile使我的线程死锁。即使过程存在仍然相同。我听说你必须关闭Write Pipe但是这样做时它什么都不读。

这是我的代码:

var
  saSec : TSecurityAttributes;
  hRead, hWrite : THandle;
  SI : TStartupInfo;
  PI : TProcessInformation;
  Running,dwRead : DWORD;
  buf : array [0..1024] of AnsiChar;
  data : AnsiString;
begin
  saSec.nLength := sizeof(TSecurityAttributes);
  saSec.bInheritHandle := false;
  saSec.lpSecurityDescriptor := nil;

  if CreatePipe(hRead, hWrite, @saSec, 0) then
  begin
     FillChar(SI, Sizeof(TStartupInfo), #0);
     FillChar(PI, Sizeof(TProcessInformation), #0);
     SI.hStdInput := hRead;
     SI.hStdOutput := hWrite;
     SI.hStdError := hWrite;
     SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
     SI.wShowWindow := SW_HIDE;

     if CreateProcess(nil, PChar('openvpn' + cert), @saSec, @saSec, False, NORMAL_PRIORITY_CLASS, nil, nil, SI, PI) then
     begin
          data := '';
          repeat
            Running := WaitForSingleObject(PI.hProcess, 100);
            repeat
                  FillChar(buf, sizeof(buf), #0);
                  ReadFile(hRead, buf, sizeof(buf), dwRead, nil);
                  data := data + buf;
                   if Pos('sequence completed', data) >0 then
                  begin
                    status := 1;
                    Synchronize(Sync);
                  end;
            until dwRead < sizeof(buf);

          until Running <> WAIT_TIMEOUT ;
          status := 0;
          Synchronize(Sync);
          CloseHandle(PI.hProcess);
          CloseHandle(PI.hThread);
     end;

1 个答案:

答案 0 :(得分:0)

除非您使用重叠I / O,否则ReadFile将阻塞,直到从正在读取的句柄中获取数据,或者直到句柄上出现某些错误情况。

你正在等待从管道中读取什么都没有写入。您在创建句柄时禁用了继承,因此您创建的进程将不会接收它们。分配到saSec.bInheritHandle时允许继承,至少在调用CreatePipe之前。 (如果您不希望后续进程可以继承新进程和线程句柄,则可以更改它以准备CreateProcess。)还要注意CreateProcess的第五个参数,它控制相同的的事情。

Raymond Chen几年前发表了article expanding on the topic of inheriting handles