繁体   English   中英

Delphi XE8:运行外部控制台应用程序,等待其结果并捕获其结果时出现问题

[英]Delphi XE8: problems running an external console application, waiting for its results and capturing its results

在Windows下的Delphi XE8中,我试图调用一个外部控制台应用程序并捕获其输出。 我使用以下代码,如从DOS(命令/控制台)窗口捕获输出以及从Shell / DOS应用程序将输出获取到Delphi应用程序中所述

procedure TForm1.Button1Click(Sender: TObject) ;

  procedure RunDosInMemo(DosApp:String;AMemo:TMemo) ;
  const
    ReadBuffer = 2400;
  var
    Security : TSecurityAttributes;
    ReadPipe,WritePipe : THandle;
    start : TStartUpInfo;
    ProcessInfo : TProcessInformation;
    Buffer : Pchar;
    BytesRead : DWord;
    Apprunning : DWord;
    S: String;
  begin
    With Security do begin
      nlength := SizeOf(TSecurityAttributes) ;
      binherithandle := true;
      lpsecuritydescriptor := nil;
    end;
    if Createpipe (ReadPipe, WritePipe,
                   @Security, 0) then 
    begin
      Buffer := AllocMem(ReadBuffer + 1) ;
      FillChar(Start,Sizeof(Start),#0) ;
      start.cb := SizeOf(start) ;
      start.hStdOutput := WritePipe;
      start.hStdInput := ReadPipe;
      start.dwFlags := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW;
      start.wShowWindow := SW_HIDE;

      S:=UniqueString(DosApp);
      if CreateProcess(nil,
              PChar(S),
              @Security,
              @Security,
              true,
              NORMAL_PRIORITY_CLASS,
              nil,
              nil,
              start,
              ProcessInfo) then
      begin
        repeat
          Apprunning := WaitForSingleObject
                        (ProcessInfo.hProcess,100) ;
          Application.ProcessMessages;
        until (Apprunning <> WAIT_TIMEOUT) ;
        Repeat
          BytesRead := 0;
          ReadFile(ReadPipe,Buffer[0], ReadBuffer,BytesRead,nil) ;
          Buffer[BytesRead]:= #0;
          OemToAnsi(Buffer,Buffer) ;
          AMemo.Text := AMemo.text + String(Buffer) ;
        until (BytesRead < ReadBuffer) ;
      end;
      FreeMem(Buffer) ;
      CloseHandle(ProcessInfo.hProcess) ;
      CloseHandle(ProcessInfo.hThread) ;
      CloseHandle(ReadPipe) ;
      CloseHandle(WritePipe) ;
    end;
  end;

begin {button 1 code}
  RunDosInMemo('cmd.exe /c dir',Memo1) ; //<-- this works
  RunDosInMemo('"c:\consoleapp.exe" "/parameter"',Memo1) //<-- this hangs in the repeat until (Apprunning <> WAIT_TIMEOUT) ; 
end;

它适用于DOS命令,但不适用于控制台应用程序。 控制台应用程序将启动并正确执行,但会repeat until (Apprunning <> WAIT_TIMEOUT)挂起, repeat until (Apprunning <> WAIT_TIMEOUT)循环repeat until (Apprunning <> WAIT_TIMEOUT) 我可以尝试解决什么问题?

非常感谢你!

您正在运行的程序期望输入(例如从键盘输入)或产生比管道缓冲区适合的输出更多的输出。 无论哪种情况,该程序都会挂起,等待进一步的I / O操作,但是您的父程序正在等待该子项终止,然后再处理任何输出,并且从不提供任何输入。

您需要在程序仍在运行时处理输出管道。 否则,您可能会冒缓冲区被填满的风险,并且孩子将阻塞直到有更多空间可用为止。 同样,如果您不打算向其他进程提供任何输入,则可能不应该为其提供有效的输入句柄。 这样,如果它尝试读取输入,它将失败而不是阻塞。

此外,您为该程序指定的输入句柄将附加到输出句柄。 如果程序尝试读取,它将读取自己的输出,例如I / O拾音器。 要处理输入输出,您需要两个管道。

(请注意,此死锁正是我在您所使用的答案的注释中提到的问题。同一答案中的第二个代码块解决了该问题以及我们的风衣蛇问题。)

总结一下:@David Heffernan在Execute DOS程序中的代码并动态获取输出 问题是控制台应用程序发出UTF-16。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM