function RunWaitAndCaptureOutput(CommandLine: string; var Output: string): DWord;
const BufSize = 1024;
var
buf : array[0..BufSize - 1] of char;
si : STARTUPINFO;
sa : SECURITY_ATTRIBUTES;
sd : SECURITY_DESCRIPTOR; //security information for pipes
pi : PROCESS_INFORMATION;
// newstdin,
newstdout,
read_stdout : THandle;
// write_stdin:THandle; //pipe handles
bytes_read : cardinal;
bytes_available : cardinal;
procedure ZeroBuffer;
begin
FillChar(Buf, SizeOf(Buf), 0);
end;
procedure RaiseError(str: string);
var n : DWord;
begin
n := GetLastError;
raise EReadError.CreateFmt('%s: %d/0x%x -%s', [Str, n, n, SysErrorMessage(n)]);
//raise ERedirectorError.CreateFmt('%s: %d/0x%x -%s',[Str,n,n,SysErrorMessage(n)]);
end;
procedure GetData;
begin
PeekNamedPipe(read_stdout, @buf, BufSize - 1, @bytes_read, @bytes_available, nil);
//check to see if there is any data to read from stdout
if (bytes_read <> 0) then
begin
ZeroBuffer;
if (bytes_available > BufSize - 1)
then
while (bytes_read >= BufSize - 1) do
begin
ReadFile(read_stdout, buf, BufSize - 1, bytes_read, nil); //read the stdout pipe
Output := Output + Buf;
ZeroBuffer;
end
else
begin
ReadFile(read_stdout, buf, BufSize - 1, bytes_read, nil);
Output := Output + Buf;
end;
end;
end;
begin
Output := '';
Result := 255; // indicate some error
if IsWindowsNT then //initialize security descriptor (Windows NT)
begin
InitializeSecurityDescriptor(@sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(@sd, true, nil, False);
sa.lpSecurityDescriptor := @sd;
end
else
sa.lpSecurityDescriptor := nil;
sa.nLength := sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle := true; //allow inheritable handles
(*
if not(CreatePipe(newstdin,write_stdin,@sa,0)) //create stdin pipe
then RaiseError('CreatePipe');
*)
if not (CreatePipe(read_stdout, newstdout, @sa, 0)) then
begin
// CloseHandle(newstdin);
// CloseHandle(write_stdin);
RaiseError('CreatePipe');
end;
GetStartupInfo(si); //set startupinfo for the spawned process
{
The dwFlags member tells CreateProcess how to make the process.
STARTF_USESTDHANDLES validates the hStd* members. STARTF_USESHOWWINDOW
validates the wShowWindow member.
}
si.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
si.wShowWindow := SW_HIDE;
si.hStdOutput := newstdout;
si.hStdError := newstdout; //set the new handles for the child process
// si.hStdInput:=newstdin;
//spawn the child process
if not (CreateProcess(nil, PChar(CommandLine), nil, nil, TRUE, CREATE_NEW_CONSOLE,
nil, nil, si, pi))
then
begin
// CloseHandle(newstdin);
CloseHandle(newstdout);
CloseHandle(read_stdout);
// CloseHandle(write_stdin);
RaiseError('CreateProcess');
end;
ZeroBuffer;
while True do
begin
GetExitCodeProcess(pi.hProcess, Result); //while the process is running
if (Result <> STILL_ACTIVE) then break;
GetData;
end;
GetData;
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
// CloseHandle(newstdin); //clean stuff up
CloseHandle(newstdout);
CloseHandle(read_stdout);
// CloseHandle(write_stdin);
end;