Skip to content

Instantly share code, notes, and snippets.

@mmmunk
Last active May 14, 2018 11:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmmunk/cbe059f06c42f60724ccdcf58f60a2b9 to your computer and use it in GitHub Desktop.
Save mmmunk/cbe059f06c42f60724ccdcf58f60a2b9 to your computer and use it in GitHub Desktop.
Delphi procedure to run an external command line program and capture and display the output.
procedure RunProcessAndCaptureOutput(const CmdLine: string; Memo: TMemo; HideLinesCount: Integer = 0);
var
SecAttr: TSecurityAttributes;
PipeR, PipeW: THandle;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
Buffer: packed array[0..4096-1] of AnsiChar;
Count: Cardinal;
S, Leftover: AnsiString;
i, P: Cardinal;
C: AnsiChar;
begin
SecAttr.nLength:=SizeOf(SecAttr);
SecAttr.lpSecurityDescriptor:=nil;
SecAttr.bInheritHandle:=True;
if not CreatePipe(PipeR, PipeW, @SecAttr, 0) then
raise Exception.Create('CreatePipe: '+SysErrorMessage(GetLastError));
SetHandleInformation(PipeR, HANDLE_FLAG_INHERIT, 0);
FillChar(StartupInfo, SizeOf(StartupInfo), 0);
StartupInfo.cb:=SizeOf(StartupInfo);
StartupInfo.dwFlags:=STARTF_USESTDHANDLES;
StartupInfo.hStdOutput:=PipeW;
StartupInfo.hStdError:=PipeW;
FillChar(ProcessInfo, SizeOf(ProcessInfo), 0);
if not CreateProcess(nil, PChar(CmdLine), nil, nil, True, CREATE_NO_WINDOW, nil, nil, StartupInfo, ProcessInfo) then
raise Exception.Create('CreateProcess: '+SysErrorMessage(GetLastError));
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
CloseHandle(PipeW);
Leftover:='';
while ReadFile(PipeR, Buffer[0], SizeOf(Buffer)-1, Count, nil) and (Count > 0) do
begin
Buffer[Count]:=#0;
i:=0;
P:=0;
while i < Count do
begin
C:=Buffer[i];
if C in [#10, #13] then
begin
if HideLinesCount > 0 then
Dec(HideLinesCount)
else
begin
Buffer[i]:=#0;
S:=Leftover+AnsiString(PAnsiChar(@Buffer[P]));
OemToCharBuffA(@S[1], @S[1], Length(S));
Memo.Lines.Add(string(S));
end;
Leftover:='';
case C of
#10: if Buffer[i+1] = #13 then Inc(i);
#13: if Buffer[i+1] = #10 then Inc(i);
end;
P:=i+1;
end;
Inc(i);
end;
Leftover:=AnsiString(PAnsiChar(@Buffer[P]));
Application.ProcessMessages;
end;
if (Leftover <> '') and (HideLinesCount <= 0) then
begin
OemToCharBuffA(@Leftover[1], @Leftover[1], Length(Leftover));
Memo.Lines.Add(string(Leftover));
end;
CloseHandle(PipeR);
end;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment