Author: Jonas Bilinkevicius
Does anyone have a working example of a GUI application that redirects the screen
output from a console application? I've tried it using the CreateProcess API
function, however it only works for me when I launch it through the D5 UI, but not
when I double click the compiled executable.
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 default}
35 );
36 try
37 {Make child process use StdOutPipeWrite as standard out, and
38 make sure it does not show on screen}
39 with SI do
40 begin
41 FillChar(SI, SizeOf(SI), 0);
42 cb := SizeOf(SI);
43 dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
44 wShowWindow := SW_HIDE;
45 hStdInput := GetStdHandle(STD_INPUT_HANDLE); {don't redirect stdinput}
46 hStdOutput := StdOutPipeWrite;
47 hStdError := StdOutPipeWrite;
48 end;
49 {launch the command line compiler
50 WorkDir := 'C:\';}
51 WorkDir := '';
52 WasOK := CreateProcess(nil, PChar(CommandLine), nil, nil, True, 0, nil, nil, SI,
53 PI);
54 {Now that the handle has been inherited, close write to be safe.We don't
55 want to read or write to it accidentally}
56 CloseHandle(StdOutPipeWrite);
57 {if process could be created then handle its output}
58 if not WasOK then
59 raise Exception.Create('Could not execute command line!')
60 else
61 try
62 {get all output until DOS app finishes}
63 Line := '';
64 repeat
65 {read block of characters (might contain carriage returns and line feeds)}
66 WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
67 {has anything been read?}
68 if BytesRead > 0 then
69 begin
70 {finish buffer to PChar}
71 Buffer[BytesRead] := #0;
72 {combine the buffer with the rest of the last run}
73 Line := Line + Buffer;
74 end;
75 until
76 not WasOK or (BytesRead = 0);
77 {wait for console app to finish (should be already at this point)}
78 WaitForSingleObject(PI.hProcess, INFINITE);
79 finally
80 {Close all remaining handles}
81 CloseHandle(PI.hThread);
82 CloseHandle(PI.hProcess);
83 end;
84 finally
85 result := Line;
86 CloseHandle(StdOutPipeRead);
87 end;
88 end;
89
90 end.
|