Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save hotsoft-desenv2/bed7a75bbe19f19b163d2059fe85c57e to your computer and use it in GitHub Desktop.
Save hotsoft-desenv2/bed7a75bbe19f19b163d2059fe85c57e to your computer and use it in GitHub Desktop.
Delphi Execute a Console Program and Capture Its Output
function ExecAndCapture(const ACmdLine: string; var AOutput: string): Integer;
const
cBufferSize = 2048;
var
vBuffer: Pointer;
vStartupInfo: TStartUpInfo;
vSecurityAttributes: TSecurityAttributes;
vReadBytes: DWord;
vProcessInfo: TProcessInformation;
vStdInPipe : TAnoPipe;
vStdOutPipe: TAnoPipe;
begin
Result := 0;
with vSecurityAttributes do
begin
nlength := SizeOf(TSecurityAttributes);
binherithandle := True;
lpsecuritydescriptor := nil;
end;
// Create anonymous pipe for standard input
if not CreatePipe(vStdInPipe.Output, vStdInPipe.Input, @vSecurityAttributes, 0) then
raise Exception.Create('Failed to create pipe for standard input. System error message: ' + SysErrorMessage(GetLastError));
try
// Create anonymous pipe for standard output (and also for standard error)
if not CreatePipe(vStdOutPipe.Output, vStdOutPipe.Input, @vSecurityAttributes, 0) then
raise Exception.Create('Failed to create pipe for standard output. System error message: ' + SysErrorMessage(GetLastError));
try
GetMem(vBuffer, cBufferSize);
try
// initialize the startup info to match our purpose
FillChar(vStartupInfo, Sizeof(TStartUpInfo), #0);
vStartupInfo.cb := SizeOf(TStartUpInfo);
vStartupInfo.wShowWindow:= SW_HIDE; // we don't want to show the process
// assign our pipe for the process' standard input
vStartupInfo.hStdInput := vStdInPipe.Output;
// assign our pipe for the process' standard output
vStartupInfo.hStdOutput := vStdOutPipe.Input;
vStartupInfo.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
if not CreateProcess(nil
, PChar(ACmdLine)
, @vSecurityAttributes
, @vSecurityAttributes
, True
, NORMAL_PRIORITY_CLASS
, nil
, nil
, vStartupInfo
, vProcessInfo) then
raise Exception.Create('Failed creating the console process. System error msg: ' + SysErrorMessage(GetLastError));
try
// wait until the console program terminated
while WaitForSingleObject(vProcessInfo.hProcess, 50)=WAIT_TIMEOUT do
Sleep(0);
// clear the output storage
AOutput := '';
// Read text returned by the console program in its StdOut channel
repeat
ReadFile(vStdOutPipe.Output, vBuffer^, cBufferSize, vReadBytes, nil);
if vReadBytes > 0 then
begin
AOutput := AOutput + StrPas(vBuffer);
Inc(Result, vReadBytes);
end;
until (vReadBytes < cBufferSize);
finally
CloseHandle(vProcessInfo.hProcess);
CloseHandle(vProcessInfo.hThread);
end;
finally
FreeMem(vBuffer);
end;
finally
CloseHandle(vStdOutPipe.Input);
CloseHandle(vStdOutPipe.Output);
end;
finally
CloseHandle(vStdInPipe.Input);
CloseHandle(vStdInPipe.Output);
end;
end;
@KVPV
Copy link

KVPV commented Jun 26, 2023

Solution for VCL

while WaitForSingleObject(vProcessInfo.hProcess, 50)=WAIT_TIMEOUT do
             Application.ProcessMessages;

For NON-VCL

while WaitForSingleObject(vProcessInfo.hProcess, 50)=WAIT_TIMEOUT do
            Sleep(0);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment