Mega Code Archive

 
Categories / Delphi / Examples
 

Capturing all of the Output from a Console application

Title: Capturing all of the Output from a Console application Question: Use the function GetDosOutput in your application to capture all the output from a DOS application (this version only supports 32-bit console applications for how to do this with 16 bit see the update to this article http://www.delphi3000.com/articles/article_2298.asp). Code recieved from Mike Lischke (Team JEDI) in response to a question I asked on the borland winapi newsgroup. It came from his app "Compiler Generator" (www.lischke-online.de/DCG.html) and then was converted to the GetDosOutput function by me. You can contact me at johnwlong@characterlink.net. Answer: unit consoleoutput; interface uses Controls, Windows, SysUtils, Forms; function GetDosOutput(const CommandLine:string): string; implementation function GetDosOutput(const CommandLine:string): string; var SA: TSecurityAttributes; SI: TStartupInfo; PI: TProcessInformation; StdOutPipeRead, StdOutPipeWrite: THandle; WasOK: Boolean; Buffer: array[0..255] of Char; BytesRead: Cardinal; WorkDir, Line: String; begin Application.ProcessMessages; with SA do begin nLength := SizeOf(SA); bInheritHandle := True; lpSecurityDescriptor := nil; end; // create pipe for standard output redirection CreatePipe(StdOutPipeRead, // read handle StdOutPipeWrite, // write handle @SA, // security attributes 0 // number of bytes reserved for pipe - 0 default ); try // Make child process use StdOutPipeWrite as standard out, // and make sure it does not show on screen. 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 std input hStdOutput := StdOutPipeWrite; hStdError := StdOutPipeWrite; end; // launch the command line compiler WorkDir := ExtractFilePath(CommandLine); WasOK := CreateProcess(nil, PChar(CommandLine), nil, nil, True, 0, nil, PChar(WorkDir), SI, PI); // Now that the handle has been inherited, close write to be safe. // We don't want to read or write to it accidentally. CloseHandle(StdOutPipeWrite); // if process could be created then handle its output if not WasOK then raise Exception.Create('Could not execute command line!') else try // get all output until dos app finishes Line := ''; repeat // read block of characters (might contain carriage returns and line feeds) WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil); // has anything been read? if BytesRead 0 then begin // finish buffer to PChar Buffer[BytesRead] := #0; // combine the buffer with the rest of the last run Line := Line + Buffer; end; until not WasOK or (BytesRead = 0); // wait for console app to finish (should be already at this point) WaitForSingleObject(PI.hProcess, INFINITE); finally // Close all remaining handles CloseHandle(PI.hThread); CloseHandle(PI.hProcess); end; finally result:=Line; CloseHandle(StdOutPipeRead); end; end; end.