1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
unit DosCommandUnit;
interface
uses Vcl.StdCtrls, Windows, System.Classes, Forms, Vcl.ComCtrls;
type
TArg<T> = reference to procedure(const Arg: T);
ConsoleOutputThread = class( TThread )
private
protected
procedure Execute; override;
public
ACommand: string;
CallBackRunTime, CallBackTerminate: TArg<String>;
end;
function startConsole(_ACommand: String; _CallBackRunTime, _CallBackTerminate: TArg<String>) : ConsoleOutputThread;
procedure stopConsole(OutputThreadHandle : ConsoleOutputThread);
implementation
{ ConsoleOutput }
procedure ConsoleOutputThread.Execute;
const
CReadBuffer = 2400;
var
saSecurity: TSecurityAttributes;
hRead: THandle;
hWrite: THandle;
suiStartup: TStartupInfo;
piProcess: TProcessInformation;
pBuffer: array [0 .. CReadBuffer] of AnsiChar;
dBuffer: array [0 .. CReadBuffer] of AnsiChar;
dRead: DWORD;
dRunning: DWORD;
dAvailable: DWORD;
begin
saSecurity.nLength := SizeOf(TSecurityAttributes);
saSecurity.bInheritHandle := true;
saSecurity.lpSecurityDescriptor := nil;
if CreatePipe(hRead, hWrite, @saSecurity, 0) then
try
FillChar(suiStartup, SizeOf(TStartupInfo), #0);
suiStartup.cb := SizeOf(TStartupInfo);
suiStartup.hStdInput := hRead;
suiStartup.hStdOutput := hWrite;
suiStartup.hStdError := hWrite;
suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
suiStartup.wShowWindow := SW_HIDE;
if CreateProcessW(
nil,
PChar('cmd.exe /C ' + ACommand),
@saSecurity,
@saSecurity,
true,
NORMAL_PRIORITY_CLASS,
nil,
nil,
suiStartup,
piProcess) then
try
repeat
dRunning := WaitForSingleObject(piProcess.hProcess, 100);
PeekNamedPipe(hRead, nil, 0, nil, @dAvailable, nil);
if (dAvailable > 0) then
repeat
dRead := 0;
ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
pBuffer[dRead] := #0;
OemToCharA(pBuffer, dBuffer);
CallBackRunTime(dBuffer);
until dRead < CReadBuffer;
Application.ProcessMessages;
until dRunning <> WAIT_TIMEOUT;
finally
CloseHandle( piProcess.hProcess );
CloseHandle( piProcess.hThread );
end;
finally
CloseHandle(hRead);
CloseHandle(hWrite);
CallBackTerminate('');
end;
end;
function startConsole(_ACommand: String; _CallBackRunTime, _CallBackTerminate: TArg<String>) : ConsoleOutputThread;
var
consoleOThrd: ConsoleOutputThread;
begin
consoleOThrd := ConsoleOutputThread.Create(true);
with consoleOThrd do begin
ACommand := _ACommand;
CallBackRunTime := _CallBackRunTime;
CallBackTerminate := _CallBackTerminate;
FreeOnTerminate := TRUE;
Resume;
end;
Result := consoleOThrd;
end;
procedure stopConsole(OutputThreadHandle : ConsoleOutputThread);
begin
OutputThreadHandle.Terminate;
while not(OutputThreadHandle.Terminated) do sleep (100);
end;
end. |
Partager