PeterDelphin
asked on
How to get the output from a console program in real-time?
In a Delphi XE7/8 program, I want to capture the output of a console program in REALTIME, e.g. inside a TMemo. For this I have created a test console program which outputs a text every 2 seconds:
Then I use a code I have found on http://stackoverflow.com/q uestions/9 119999/get ting-outpu t-from-a-s hell-dos-a pp-into-a- delphi-app
Then I call the console program with this code:
This works, HOWEVER the output in the memo is not in real-time (i.e. one line each two seconds) BUT once in one step when the console program closes:
So how can I output the lines from the console program in REAL-TIME?
program GetDosOutput_Console_Test;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
begin
try
Writeln('1 of 5');
Sleep(2000);
Writeln('2 of 5');
Sleep(2000);
Writeln('3 of 5');
Sleep(2000);
Writeln('4 of 5');
Sleep(2000);
Writeln('5 of 5');
Sleep(2000);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Then I use a code I have found on http://stackoverflow.com/q
function GetDosOutput(CommandLine: string; Work: string = 'C:\'): string;
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
StdOutPipeRead, StdOutPipeWrite: THandle;
WasOK: Boolean;
Buffer: array [0 .. 255] of AnsiChar;
BytesRead: Cardinal;
WorkDir: string;
Handle: Boolean;
begin
Result := '';
with SA do
begin
nLength := SizeOf(SA);
bInheritHandle := True;
lpSecurityDescriptor := nil;
end;
CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
try
with SI do
begin
FillChar(SI, SizeOf(SI), 0);
cb := SizeOf(SI);
dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
wShowWindow := SW_HIDE;
hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
hStdOutput := StdOutPipeWrite;
hStdError := StdOutPipeWrite;
end;
WorkDir := Work;
Handle := CreateProcess(nil, PChar('cmd.exe /C ' + CommandLine), nil, nil,
True, 0, nil, PChar(WorkDir), SI, PI);
CloseHandle(StdOutPipeWrite);
if Handle then
try
repeat
WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
if BytesRead > 0 then
begin
Buffer[BytesRead] := #0;
Result := Result + Buffer;
Form1.mmoOutput.Lines.Add(Result); // <<<<<<<<<<<<<<<<<<< output
end;
until not WasOK or (BytesRead = 0);
WaitForSingleObject(PI.hProcess, INFINITE);
finally
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
end;
finally
CloseHandle(StdOutPipeRead);
end;
end;
Then I call the console program with this code:
GetDosOutput(edtConsoleExe.Text);
This works, HOWEVER the output in the memo is not in real-time (i.e. one line each two seconds) BUT once in one step when the console program closes:
So how can I output the lines from the console program in REAL-TIME?
ASKER
Kyle, I did as you wrote. But it does not work, I still get no real-time output. Only the whole output when the console program terminates.
ASKER
I also tried this one:
However, with this code I always get this compiler error:
[dcc32 Error] GetDosOutput_Master_MainFo rm.pas(151 ): E2250 There is no overloaded version of 'Execute' that can be called with these arguments
Maybe someone could provide a working example using JclSysUtils.Execute?
procedure GetThisDosOutput(const Text: string);
begin
Form1.mmoOutput.Lines.Add(Text);
end;
procedure TForm1.btnStartConsoleExeClick(Sender: TObject);
begin
JclSysUtils.Execute(edtConsoleExe.Text, nil, @GetThisDosOutput, False, ppNormal);
end;
However, with this code I always get this compiler error:
[dcc32 Error] GetDosOutput_Master_MainFo
Maybe someone could provide a working example using JclSysUtils.Execute?
ASKER
There is also another code here: http://delphi.wikia.com/wi ki/Capture _Console_O utput_Real time_To_Me mo
However, also with this code I get a Delphi XE7 compiler error on the line with OemToAnsi(pBuffer, pBuffer);.
Maybe someone could give me a hint on how to make this code work?
However, also with this code I get a Delphi XE7 compiler error on the line with OemToAnsi(pBuffer, pBuffer);.
Maybe someone could give me a hint on how to make this code work?
ASKER
Even this code does not output in real-time:
http://thundaxsoftware.blo gspot.co.u k/2012/12/ capturing- console-ou tput-with- delphi.htm l
http://thundaxsoftware.blo
ASKER
There seems to be something wrong with my console program. I tried this code (answer from David Heffernan):
http://stackoverflow.com/q uestions/2 5723807/ex ecute-dos- program-an d-get-outp ut-dynamic ally
With this code I still get no real-time output (only when the console program terminates) with my console program (see above), but I do get real-time output with a youtube-downloader console program (https://github.com/rg3/you tube-dl/bl ob/master/ README.md)
WHY?
http://stackoverflow.com/q
With this code I still get no real-time output (only when the console program terminates) with my console program (see above), but I do get real-time output with a youtube-downloader console program (https://github.com/rg3/you
WHY?
Try to replace Sleep(2000) by SoftDelay(2000):
procedure SoftDelay(ADelay: UInt64);
var
TickCount: UInt64;
begin
TickCount:=GetTickCount64;
repeat
Application.ProcessMessages;
until GetTickCount64-TickCount > ADelay;
end;
ASKER
Even with SoftDelay I don't get real-time output from GetDosOutput_Console_Test with the code of David Heffernan, only when GetDosOutput_Console_Test. exe terminates.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
why look on another site ?
epasquier seems to have stopped posting ... can't blame him, not much activity here anymore compared to before
https://www.experts-exchange.com/questions/27460239/get-stdout-and-stderr-of-an-exe-program-inside-Delphi.html
epasquier seems to have stopped posting ... can't blame him, not much activity here anymore compared to before
https://www.experts-exchange.com/questions/27460239/get-stdout-and-stderr-of-an-exe-program-inside-Delphi.html
ASKER
Thank you for the solution!
And sorry for the long delay! Was away!
And sorry for the long delay! Was away!
EG:
Form1.mmoOutput.Lines.Add(
Application.ProcessMessage