Запуск программ с передачей консольного ввода и чтением вывода

Советы » DOS и Консоль » Запуск программ с передачей консольного ввода и чтением вывода

о пример запуска консольных программ с передачей ей консольного ввода (как если бы он был введен с клавиатуры после запуска программы) и чтением консольного вывода. Таким способом можно запускать например стандартный виндовый ftp.exe (в невидимом окне) и тем самым отказаться от использования специализированных, зачастую глючных компонент.

function

ExecuteFile(FileName, StdInput: string

; TimeOut: integer; var

StdOutput: string

): boolean; label

Error; type

TPipeHandles = (IN_WRITE, IN_READ, OUT_WRITE, OUT_READ, ERR_WRITE, ERR_READ); type

TPipeArray = array

[TPipeHandles] of

THandle; var

i: integer; ph: TPipeHandles; sa: TSecurityAttributes; Pipes: TPipeArray; StartInf: TStartupInfo; ProcInf: TProcessInformation; Buf: array

[0..1024] of

byte; TimeStart: TDateTime; function

ReadOutput: string

; var

i: integer; s: string

; BytesRead: longint; begin

Result := ''; repeat

Buf[0] := 26; WriteFile(Pipes[OUT_WRITE], Buf, 1, BytesRead, nil

); if

ReadFile(Pipes[OUT_READ], Buf, 1024, BytesRead, nil

) then

begin

if

BytesRead > 0 then

begin

buf[BytesRead] := 0; s := StrPas(@Buf[0]); i := Pos(#26, s); if

i > 0 then

s := copy(s, 1, i - 1); Result := Result + s; end

; end

; if

BytesRead1024 then

break; until

false; end

; begin

Result := false; for

ph := Low(TPipeHandles) to

High(TPipeHandles) do

Pipes[ph] := INVALID_HANDLE_VALUE; // Создаем пайпы sa.nLength := sizeof(sa); sa.bInheritHandle := TRUE; sa.lpSecurityDescriptor := nil

; if

not

CreatePipe(Pipes[IN_READ], Pipes[IN_WRITE], @sa, 0) then

goto

Error; if

not

CreatePipe(Pipes[OUT_READ], Pipes[OUT_WRITE], @sa, 0) then

goto

Error; if

not

CreatePipe(Pipes[ERR_READ], Pipes[ERR_WRITE], @sa, 0) then

goto

Error; // Пишем StdIn StrPCopy(@Buf[0], stdInput + ^Z); WriteFile(Pipes[IN_WRITE], Buf, Length(stdInput), i, nil

); // Хендл записи в StdIn надо закрыть - иначе выполняемая программа // может не прочитать или прочитать не весь StdIn. CloseHandle(Pipes[IN_WRITE]); Pipes[IN_WRITE] := INVALID_HANDLE_VALUE; FillChar(StartInf, sizeof(TStartupInfo), 0); StartInf.cb := sizeof(TStartupInfo); StartInf.dwFlags := STARTF_USESHOWWINDOW or

STARTF_USESTDHANDLES; StartInf.wShowWindow := SW_SHOW; // SW_HIDE если надо запустить невидимо StartInf.hStdInput := Pipes[IN_READ]; StartInf.hStdOutput := Pipes[OUT_WRITE]; StartInf.hStdError := Pipes[ERR_WRITE]; if

not

CreateProcess(nil

, PChar(FileName), nil

, nil

, True, NORMAL_PRIORITY_CLASS, nil

, nil

, StartInf, ProcInf) then

goto

Error; TimeStart := Now; repeat

Application.ProcessMessages; i := WaitForSingleObject(ProcInf.hProcess, 100); if

i = WAIT_OBJECT_0 then

break; if

(Now - TimeStart) * SecsPerDay > TimeOut then

break; until

false; if

iWAIT_OBJECT_0 then

goto

Error; StdOutput := ReadOutput; for

ph := Low(TPipeHandles) to

High(TPipeHandles) do

if

Pipes[ph]INVALID_HANDLE_VALUE then

CloseHandle(Pipes[ph]); CloseHandle(ProcInf.hProcess); CloseHandle(ProcInf.hThread); Result := true; Exit; Error: if

ProcInf.hProcessINVALID_HANDLE_VALUE then

begin

CloseHandle(ProcInf.hThread); i := WaitForSingleObject(ProcInf.hProcess, 1000); CloseHandle(ProcInf.hProcess); if

iWAIT_OBJECT_0 then

begin

ProcInf.hProcess := OpenProcess(PROCESS_TERMINATE, FALSE, ProcInf.dwProcessId); if

ProcInf.hProcess 0 then

begin

TerminateProcess(ProcInf.hProcess, 0); CloseHandle(ProcInf.hProcess); end

; end

; end

; for

ph := Low(TPipeHandles) to

High(TPipeHandles) do

if

Pipes[ph]INVALID_HANDLE_VALUE then

CloseHandle(Pipes[ph]); end

;

Другое по теме:

Категории

Статьи

Советы

Copyright © 2022 - All Rights Reserved - www.delphirus.com