I'm using the following to capture the output of a OS console command.
My problem is that this code buffers all output until the command is complete before displaying it and I'd like to display the output in realtime, or at least line by line (while still being able to track when the command finishes execution if possible.
I'm thinking that I might be able to do this by appending the last chunk of buffer to the
TMemo (
mOutput) within the while...do, but I just can't figure it out.
procedure TmainForm.ActionButtonClick(Sender: TObject);
const
READ_BYTES = 2048;
var
OutputLines: TStringList;
MemStream: TMemoryStream;
OurProcess: TProcess;
NumBytes: LongInt;
BytesRead: LongInt;
userInput: String;
begin
// A temp Memorystream is used to buffer the output
MemStream := TMemoryStream.Create;
BytesRead := 0;
OurProcess := TProcess.Create(nil);
OurProcess.Executable := 'netstat';
OurProcess.Parameters.Add('-a');
OurProcess.Options := [poUsePipes, poNoConsole];
OurProcess.Execute;
while True do
begin
// make sure we have room
MemStream.SetSize(BytesRead + READ_BYTES);
// try reading it
NumBytes := OurProcess.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES);
if NumBytes > 0 // All read() calls will block, except the final one.
then begin
Inc(BytesRead, NumBytes);
end else
BREAK // Program has finished execution.
end;
MemStream.SetSize(BytesRead);
OutputLines := TStringList.Create;
OutputLines.LoadFromStream(MemStream);
mOutput.Lines.AddStrings(OutputLines);
OutputLines.Free;
OurProcess.Free;
MemStream.Free;
end;
Am I on the right track? Is there a better way to do this? (Note, netstat is just used as an example here.. this could be any command that takes a while to run but outputs its progress on screen sequentially).
Thanks,
FM
[EDIT: Removed spurious
end; and reformatted to make levels clearer]