[英]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.