215 lines
5.1 KiB
ObjectPascal
215 lines
5.1 KiB
ObjectPascal
unit X2UtProcess;
|
|
|
|
interface
|
|
uses
|
|
Classes,
|
|
Windows;
|
|
|
|
type
|
|
TProcess = class(TObject)
|
|
private
|
|
FEnvironment: TStrings;
|
|
FCommandLine: String;
|
|
FVisible: Boolean;
|
|
FWorkingPath: String;
|
|
protected
|
|
function BuildEnvironment(): String;
|
|
public
|
|
constructor Create();
|
|
destructor Destroy(); override;
|
|
|
|
function Execute(const AStream: TStream; out AExitCode: Cardinal): Boolean; overload;
|
|
function Execute(const AStream: TStream): Boolean; overload;
|
|
|
|
function Execute(out AExitCode: Cardinal): String; overload;
|
|
function Execute(): String; overload;
|
|
|
|
property CommandLine: String read FCommandLine write FCommandLine;
|
|
property Environment: TStrings read FEnvironment;
|
|
property Visible: Boolean read FVisible write FVisible;
|
|
property WorkingPath: String read FWorkingPath write FWorkingPath;
|
|
end;
|
|
|
|
|
|
implementation
|
|
uses
|
|
SysUtils;
|
|
|
|
|
|
{ TProcess }
|
|
constructor TProcess.Create();
|
|
begin
|
|
inherited;
|
|
|
|
FEnvironment := TStringList.Create();
|
|
FVisible := False;
|
|
FWorkingPath := GetCurrentDir();
|
|
end;
|
|
|
|
destructor TProcess.Destroy();
|
|
begin
|
|
FreeAndNil(FEnvironment);
|
|
|
|
inherited;
|
|
end;
|
|
|
|
|
|
function TProcess.BuildEnvironment(): String;
|
|
var
|
|
charPos: Integer;
|
|
resultLength: Integer;
|
|
value: String;
|
|
valueIndex: Integer;
|
|
|
|
begin
|
|
if FEnvironment.Count = 0 then
|
|
begin
|
|
Result := '';
|
|
exit;
|
|
end;
|
|
|
|
resultLength := 1;
|
|
for valueIndex := 0 to Pred(FEnvironment.Count) do
|
|
Inc(resultLength, Length(FEnvironment[valueIndex]));
|
|
|
|
Result := StringOfChar(#0, resultLength);
|
|
charPos := 1;
|
|
|
|
for valueIndex := 0 to Pred(FEnvironment.Count) do
|
|
begin
|
|
value := FEnvironment[valueIndex];
|
|
|
|
if Length(value) > 0 then
|
|
Move(value[1], Result[charPos], Length(value));
|
|
|
|
Inc(charPos, Succ(Length(value)));
|
|
end;
|
|
end;
|
|
|
|
|
|
function TProcess.Execute(const AStream: TStream;
|
|
out AExitCode: Cardinal): Boolean;
|
|
function NilString(const AValue: String): PChar;
|
|
begin
|
|
Result := nil;
|
|
if Length(AValue) > 0 then
|
|
Result := PChar(AValue);
|
|
end;
|
|
|
|
const
|
|
BufferSize = 2048;
|
|
|
|
var
|
|
buffer: PChar;
|
|
processInfo: TProcessInformation;
|
|
readPipe: THandle;
|
|
securityAttr: TSecurityAttributes;
|
|
startupInfo: TStartupInfo;
|
|
writePipe: THandle;
|
|
bytesRead: Cardinal;
|
|
newConsole: Boolean;
|
|
consoleOutput: THandle;
|
|
bytesWritten: Cardinal;
|
|
|
|
begin
|
|
Result := False;
|
|
|
|
FillChar(processInfo, SizeOf(TProcessInformation), #0);
|
|
FillChar(startupInfo, SizeOf(TStartupInfo), #0);
|
|
FillChar(securityAttr, SizeOf(TSecurityAttributes), #0);
|
|
|
|
securityAttr.nLength := SizeOf(TSecurityAttributes);
|
|
securityAttr.lpSecurityDescriptor := nil;
|
|
securityAttr.bInheritHandle := True;
|
|
|
|
if CreatePipe(readPipe, writePipe, @securityAttr, 0) then
|
|
try
|
|
SetHandleInformation(readPipe, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
|
|
|
|
startupInfo.cb := SizeOf(TStartupInfo);
|
|
startupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
|
|
startupInfo.wShowWindow := SW_HIDE;
|
|
startupInfo.hStdOutput := writePipe;
|
|
startupInfo.hStdError := writePipe;
|
|
|
|
if CreateProcess(nil, NilString(FCommandLine), nil, nil, True, 0,
|
|
NilString(BuildEnvironment()), NilString(FWorkingPath),
|
|
startupInfo, processInfo) then
|
|
begin
|
|
CloseHandle(writePipe);
|
|
writePipe := 0;
|
|
|
|
newConsole := False;
|
|
consoleOutput := 0;
|
|
if Visible then
|
|
begin
|
|
newConsole := AllocConsole;
|
|
consoleOutput := GetStdHandle(STD_OUTPUT_HANDLE);
|
|
end;
|
|
|
|
try
|
|
GetMem(buffer, BufferSize);
|
|
try
|
|
repeat
|
|
ReadFile(readPipe, buffer^, BufferSize, bytesRead, nil);
|
|
if bytesRead > 0 then
|
|
begin
|
|
AStream.WriteBuffer(buffer^, bytesRead);
|
|
|
|
if consoleOutput <> 0 then
|
|
WriteFile(consoleOutput, buffer^, bytesRead, bytesWritten, nil);
|
|
end;
|
|
until bytesRead = 0;
|
|
finally
|
|
FreeMem(buffer, BufferSize);
|
|
end;
|
|
finally
|
|
if newConsole then
|
|
FreeConsole;
|
|
end;
|
|
|
|
GetExitCodeProcess(processInfo.hProcess, AExitCode);
|
|
Result := True;
|
|
end else
|
|
RaiseLastOSError();
|
|
finally
|
|
CloseHandle(readPipe);
|
|
if writePipe <> 0 then
|
|
CloseHandle(writePipe);
|
|
end;
|
|
end;
|
|
|
|
function TProcess.Execute(const AStream: TStream): Boolean;
|
|
var
|
|
exitCode: Cardinal;
|
|
|
|
begin
|
|
Result := Execute(AStream, exitCode);
|
|
end;
|
|
|
|
|
|
function TProcess.Execute(out AExitCode: Cardinal): String;
|
|
var
|
|
resultStream: TStringStream;
|
|
|
|
begin
|
|
Result := '';
|
|
resultStream := TStringStream.Create('');
|
|
try
|
|
if Execute(resultStream, AExitCode) then
|
|
Result := resultStream.DataString;
|
|
finally
|
|
FreeAndNil(resultStream);
|
|
end;
|
|
end;
|
|
|
|
function TProcess.Execute(): String;
|
|
var
|
|
exitCode: Cardinal;
|
|
|
|
begin
|
|
Result := Execute(exitCode);
|
|
end;
|
|
|
|
end.
|