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

 

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

Code:

function ExecuteFile(FileName,StdInput: string;

                    TimeOut: integer;

                    var StdOutput:string) : boolean;

 

label Error;

 

type

TPipeHandles = (IN_WRITEIN_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;

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


 

Code:

procedure Dos2Win(CmdLine:String; OutMemo:TMemo);

const BUFSIZE = 2000;

var SecAttr    : TSecurityAttributes;

   hReadPipe,

   hWritePipe : THandle;

   StartupInfo: TStartUpInfo;

   ProcessInfo: TProcessInformation;

   Buffer     : Pchar;

   WaitReason,

   BytesRead  : DWord;

begin

 

with SecAttr do

begin

  nlength              := SizeOf(TSecurityAttributes);

  binherithandle       := true;

  lpsecuritydescriptor := nil;

end;

// Creazione della pipe

if Createpipe (hReadPipe, hWritePipe, @SecAttr, 0) then

begin

  Buffer  := AllocMem(BUFSIZE + 1);    // Allochiamo un buffer di dimensioni BUFSIZE+1

  FillChar(StartupInfo, Sizeof(StartupInfo), #0);

  StartupInfo.cb          := SizeOf(StartupInfo);

  StartupInfo.hStdOutput  := hWritePipe;

  StartupInfo.hStdInput   := hReadPipe;

  StartupInfo.dwFlags     := STARTF_USESTDHANDLES +

                             STARTF_USESHOWWINDOW;

  StartupInfo.wShowWindow := SW_HIDE;

 

  if CreateProcess(nil,

     PChar(CmdLine),

     @SecAttr,

     @SecAttr,

     true,

     NORMAL_PRIORITY_CLASS,

     nil,

     nil,

     StartupInfo,

     ProcessInfo) then

    begin

      // Attendiamo la fine dell'esecuzione del processo

      repeat

        WaitReason := WaitForSingleObject( ProcessInfo.hProcess,100);

        Application.ProcessMessages;

      until (WaitReason <> WAIT_TIMEOUT);

      // Leggiamo la pipe

      Repeat

        BytesRead := 0;

        // Leggiamo "BUFSIZE" bytes dalla pipe

        ReadFile(hReadPipe, Buffer[0], BUFSIZE, BytesRead, nil);

        // Convertiamo in una stringa "\0 terminated"

        Buffer[BytesRead]:= #0;

        // Convertiamo i caratteri da DOS ad ANSI

        OemToAnsi(Buffer,Buffer);

        // Scriviamo nell' "OutMemo" l'output ricevuto tramite pipe

        OutMemo.Text := OutMemo.text + String(Buffer);

      until (BytesRead < BUFSIZE);

    end;

  FreeMem(Buffer);

  CloseHandle(ProcessInfo.hProcess);

  CloseHandle(ProcessInfo.hThread);

  CloseHandle(hReadPipe);

  CloseHandle(hWritePipe);

end;

end;

 


 

А это исправленный Song'ом вариант для обеспечения вывода текста в real-time:

Code:

procedure RunDosInMemo(CmdLine:String;AMemo:TMemo);

const

  ReadBuffer = 2400;

var

Security       : TSecurityAttributes;

ReadPipe,WritePipe  : THandle;

start        : TStartUpInfo;

ProcessInfo     : TProcessInformation;

Buffer        : Pchar;

BytesRead      : DWord;

Apprunning      : DWord;

begin

Screen.Cursor:=CrHourGlass;

Form1.Button1.Enabled:=False;

With Security do begin

nlength        := SizeOf(TSecurityAttributes);

binherithandle    := true;

lpsecuritydescriptor := nil;

end;

if Createpipe (ReadPipe, WritePipe,

        @Security, 0) then begin

Buffer  := AllocMem(ReadBuffer + 1);

FillChar(Start,Sizeof(Start),#0);

start.cb      := SizeOf(start);

start.hStdOutput  := WritePipe;

start.hStdInput  := ReadPipe;

start.dwFlags   := STARTF_USESTDHANDLES +

            STARTF_USESHOWWINDOW;

start.wShowWindow := SW_HIDE;

 

if CreateProcess(nil,

     PChar(CmdLine),

     @Security,

     @Security,

     true,

     NORMAL_PRIORITY_CLASS,

     nil,

     nil,

     start,

     ProcessInfo)

then

begin

  repeat

  Apprunning := WaitForSingleObject

         (ProcessInfo.hProcess,100);

   ReadFile(ReadPipe,Buffer[0],

      ReadBuffer,BytesRead,nil);

   Buffer[BytesRead]:= #0;

   OemToAnsi(Buffer,Buffer);

   AMemo.Text := AMemo.text + String(Buffer);

 

  Application.ProcessMessages;

  until (Apprunning <> WAIT_TIMEOUT);

end;

FreeMem(Buffer);

CloseHandle(ProcessInfo.hProcess);

CloseHandle(ProcessInfo.hThread);

CloseHandle(ReadPipe);

CloseHandle(WritePipe);

end;

Screen.Cursor:=CrDefault;

Form1.Button1.Enabled:=True;

end;

 

procedure TForm1.Button1Click(Sender: TObject);

begin

Memo1.Clear;

RunDosInMemo('ping -t 192.168.28.200',Memo1);

end;

 

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

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

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

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


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