簡體   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