Author: John W. Long
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 "Capturing all of the Output
from a Console application (16 bit)").
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:
1 unit consoleoutput;
2
3 interface
4
5 uses
6 Controls, Windows, SysUtils, Forms;
7
8 function GetDosOutput(const CommandLine: string): string;
9
10 implementation
11
12 function GetDosOutput(const CommandLine: string): string;
13 var
14 SA: TSecurityAttributes;
15 SI: TStartupInfo;
16 PI: TProcessInformation;
17 StdOutPipeRead, StdOutPipeWrite: THandle;
18 WasOK: Boolean;
19 Buffer: array[0..255] of Char;
20 BytesRead: Cardinal;
21 WorkDir, Line: string;
22 begin
23 Application.ProcessMessages;
24 with SA do
25 begin
26 nLength := SizeOf(SA);
27 bInheritHandle := True;
28 lpSecurityDescriptor := nil;
29 end;
30 // create pipe for standard output redirection
31 CreatePipe(StdOutPipeRead, // read handle
32 StdOutPipeWrite, // write handle
33 @SA, // security attributes
34 0 // number of bytes reserved for pipe - 0
35 default
36 );
37 try
38 // Make child process use StdOutPipeWrite as standard out,
39 // and make sure it does not show on screen.
40 with SI do
41 begin
42 FillChar(SI, SizeOf(SI), 0);
43 cb := SizeOf(SI);
44 dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
45 wShowWindow := SW_HIDE;
46 hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect std
47 input
48 hStdOutput := StdOutPipeWrite;
49 hStdError := StdOutPipeWrite;
50 end;
51
52 // launch the command line compiler
53 WorkDir := ExtractFilePath(CommandLine);
54 WasOK := CreateProcess(nil, PChar(CommandLine), nil, nil, True, 0, nil,
55 PChar(WorkDir), SI, PI);
56
57 // Now that the handle has been inherited, close write to be safe.
58 // We don't want to read or write to it accidentally.
59 CloseHandle(StdOutPipeWrite);
60 // if process could be created then handle its output
61 if not WasOK then
62 raise Exception.Create('Could not execute command line!')
63 else
64 try
65 // get all output until dos app finishes
66 Line := '';
67 repeat
68 // read block of characters (might contain carriage returns and line feeds)
69 WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
70
71 // has anything been read?
72 if BytesRead > 0 then
73 begin
74 // finish buffer to PChar
75 Buffer[BytesRead] := #0;
76 // combine the buffer with the rest of the last run
77 Line := Line + Buffer;
78 end;
79 until not WasOK or (BytesRead = 0);
80 // wait for console app to finish (should be already at this point)
81 WaitForSingleObject(PI.hProcess, INFINITE);
82 finally
83 // Close all remaining handles
84 CloseHandle(PI.hThread);
85 CloseHandle(PI.hProcess);
86 end;
87 finally
88 result := Line;
89 CloseHandle(StdOutPipeRead);
90 end;
91 end;
92
93 end.
|