Skip to content

Instantly share code, notes, and snippets.

@fabriciocolombo
Created December 13, 2012 20:00
Show Gist options
  • Select an option

  • Save fabriciocolombo/4279304 to your computer and use it in GitHub Desktop.

Select an option

Save fabriciocolombo/4279304 to your computer and use it in GitHub Desktop.

Revisions

  1. fabriciocolombo created this gist Dec 13, 2012.
    64 changes: 64 additions & 0 deletions gistfile1.pas
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,64 @@
    //Anonymous procedure approach by Lars Fosdal
    type
    TArg<T> = reference to procedure(const Arg: T);

    procedure TForm1.CaptureConsoleOutput(const ACommand, AParameters: String; CallBack: TArg<PAnsiChar>);
    const
    CReadBuffer = 2400;
    var
    saSecurity: TSecurityAttributes;
    hRead: THandle;
    hWrite: THandle;
    suiStartup: TStartupInfo;
    piProcess: TProcessInformation;
    pBuffer: array [0 .. CReadBuffer] of AnsiChar;
    dBuffer: array [0 .. CReadBuffer] of AnsiChar;
    dRead: DWORD;
    dRunning: DWORD;
    dAvailable: DWORD;
    begin
    saSecurity.nLength := SizeOf(TSecurityAttributes);
    saSecurity.bInheritHandle := true;
    saSecurity.lpSecurityDescriptor := nil;
    if CreatePipe(hRead, hWrite, @saSecurity, 0) then
    try
    FillChar(suiStartup, SizeOf(TStartupInfo), #0);
    suiStartup.cb := SizeOf(TStartupInfo);
    suiStartup.hStdInput := hRead;
    suiStartup.hStdOutput := hWrite;
    suiStartup.hStdError := hWrite;
    suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
    suiStartup.wShowWindow := SW_HIDE;
    if CreateProcess(nil, PChar(ACommand + ' ' + AParameters), @saSecurity, @saSecurity, true, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup,
    piProcess) then
    try
    repeat
    dRunning := WaitForSingleObject(piProcess.hProcess, 100);
    PeekNamedPipe(hRead, nil, 0, nil, @dAvailable, nil);
    if (dAvailable > 0) then
    repeat
    dRead := 0;
    ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
    pBuffer[dRead] := #0;
    OemToCharA(pBuffer, dBuffer);
    CallBack(dBuffer);
    until (dRead < CReadBuffer);
    Application.ProcessMessages;
    until (dRunning <> WAIT_TIMEOUT);
    finally
    CloseHandle(piProcess.hProcess);
    CloseHandle(piProcess.hThread);
    end;
    finally
    CloseHandle(hRead);
    CloseHandle(hWrite);
    end;
    end;

    usage:
    CaptureConsoleOutput('java -version', '',
    procedure(const Line: PAnsiChar)
    begin
    Memo1.Lines.Add(String(Line));
    end
    );