Содержание материала

 

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

Code:

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;

 

Автор: Алексей Бойко

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить