Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Пайпы, Проблема с пайпами 
:(
    Опции темы
XbiT
Дата 13.2.2006, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 65
Регистрация: 9.2.2006

Репутация: нет
Всего: 1



Вот собственно трабла с сабжем... Нужно открыть cmd.exe(или другую консольную прогу), передать ей команду и прочитать результат. Не могу понять, в чём проблема, т.к с пайпами работаю первый раз. Вот код(сильно не пинатьsmile):
Код

program Pipes;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Windows,
  Dialogs;

Const ExeName = 'cmd.exe';

Var
  StartupInfo : TStartupInfo;
  ProcessInfo : TProcessInformation;
  SecurityAttributes : TSecurityAttributes;
  hPipeOutRead, hPipeOutWrite : THandle;
  hPipeInRead, hPipeInWrite : THandle;
  Tmp1, Tmp2 : THandle;

Procedure ReadPipe();
Var
  Buf : array [1..255] of AnsiChar;
  BytesRead : DWord;
  i : integer;
begin
  While (ReadFile(hPipeOutRead, Buf, 255, BytesRead, nil)) and (BytesRead <> 0) do
    begin
      for i := 1 to BytesRead do
        Write(Buf[i]);
    end;
end;

Procedure WritePipe(Str : String);
Var
  Written : DWord;
  pStr : PChar;
begin
  pStr := PChar(Str+#13#10);
  WriteFile(hPipeInWrite, pStr, Length(Str), Written, nil);
end;

begin
  With SecurityAttributes do
    begin
      nLength := SizeOf(SecurityAttributes);
      bInheritHandle := true;
      lpSecurityDescriptor := nil;
    end;
  if not CreatePipe(hPipeOutRead, hPipeOutWrite, @SecurityAttributes, 0) then
    begin
      ShowMessage('CreatePipe Error :(');
      Exit;
    end;

  if not CreatePipe(hPipeInRead, hPipeInWrite, @SecurityAttributes, 0) then
    begin
      ShowMessage('CreatePipe Error :(');
      Exit;
    end;

  DuplicateHandle(GetCurrentProcess(), hPipeOutRead, GetCurrentProcess(),
                  @Tmp1, 0, False, DUPLICATE_SAME_ACCESS);
  DuplicateHandle(GetCurrentProcess(), hPipeInWrite, GetCurrentProcess(),
                  @Tmp2, 0, False, DUPLICATE_SAME_ACCESS);

  CloseHandle(hPipeOutRead);
  CloseHandle(hPipeInWrite);

  hPipeOutRead:=Tmp1;
  hPipeInWrite:=Tmp2;


  With StartupInfo do
    begin
      cb:=SizeOf(StartupInfo);
      hStdInput := hPipeInRead;
      hStdOutput := hPipeOutWrite;
      hStdError := hPipeOutWrite;
      wShowWindow := SW_HIDE;
      dwFlags := STARTF_USESTDHANDLES;
    end;
  if not CreateProcess(nil, PChar(ExeName), nil, nil, true,
                       0, nil, nil, StartupInfo, ProcessInfo) then
    begin
      ShowMessage('CreateProcess Error :(');
      Exit;
    end;
  WritePipe('dir');

  CloseHandle(hPipeInRead);
  CloseHandle(hPipeOutWrite);

  ReadPipe;

  CloseHandle(hPipeInWrite);
  CloseHandle(hPipeOutRead);
end.


Это сообщение отредактировал(а) XbiT - 14.2.2006, 01:11
PM MAIL   Вверх
Romikgy
Дата 14.2.2006, 13:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 13
Всего: 146



Код

program Pipes;
{$APPTYPE CONSOLE}
uses
  SysUtils,
  Windows,
  Dialogs;
Const ExeName = 'cmd.exe';
Var
  StartupInfo : TStartupInfo;
  ProcessInfo : TProcessInformation;
  SecurityAttributes : TSecurityAttributes;
  hPipeOutRead, hPipeOutWrite : THandle;
  hPipeInRead, hPipeInWrite : THandle;
  Tmp1, Tmp2 : THandle;
Procedure ReadPipe();
Var
  Buf : array [1..255] of AnsiChar;
  BytesRead : DWord;
  i : integer;
begin
  While (ReadFile(hPipeOutRead, Buf, 255, BytesRead, nil)) and (BytesRead <> 0) do
    begin
      for i := 1 to BytesRead do
        Write(Buf[i]);
    end;
end;
Procedure WritePipe(Str : String);
Var
  Written : DWord;
  pStr : PChar;
begin
  pStr := PChar(Str+#13#10);
  WriteFile(hPipeInWrite, pStr, Length(Str), Written, nil);
end;
begin
  With SecurityAttributes do
    begin
      nLength := SizeOf(SecurityAttributes);
      bInheritHandle := true;
      lpSecurityDescriptor := nil;
    end;
  if not CreatePipe(hPipeOutRead, hPipeOutWrite, @SecurityAttributes, 0) then
    begin
      ShowMessage('CreatePipe Error :(');
      Exit;
    end;
  if not CreatePipe(hPipeInRead, hPipeInWrite, @SecurityAttributes, 0) then
    begin
      ShowMessage('CreatePipe Error :(');
      Exit;
    end;
  DuplicateHandle(GetCurrentProcess(), hPipeOutRead, GetCurrentProcess(),
                  @Tmp1, 0, False, DUPLICATE_SAME_ACCESS);
  DuplicateHandle(GetCurrentProcess(), hPipeInWrite, GetCurrentProcess(),
                  @Tmp2, 0, False, DUPLICATE_SAME_ACCESS);
  CloseHandle(hPipeOutRead);
  CloseHandle(hPipeInWrite);
  hPipeOutRead:=Tmp1;
  hPipeInWrite:=Tmp2;
  With StartupInfo do
    begin
      cb:=SizeOf(StartupInfo);
      hStdInput := hPipeInRead;
      hStdOutput := hPipeOutWrite;
      hStdError := hPipeOutWrite;
      wShowWindow := SW_HIDE;
      dwFlags := STARTF_USESTDHANDLES;
    end;
  if not CreateProcess(nil, PChar(ExeName), nil, nil, true,
                       0, nil, nil, StartupInfo, ProcessInfo) then
    begin
      ShowMessage('CreateProcess Error :(');
      Exit;
    end;
  WritePipe('dir');
  
  ReadPipe;
  CloseHandle(hPipeInWrite);
  CloseHandle(hPipeOutRead);
end.

А так?


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
Romikgy
Дата 14.2.2006, 13:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 13
Всего: 146



Из дркб
Код

Как вывести результат работы консоли в Memo? 
 Previous  Top  Next  

      
  

Код взят из http://www.torry.net/memos.htm 


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; 
Взято с Vingrad.ru http://forum.vingrad.ru 

--------------------------------------------------------------------------------


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

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; 

Взято с Vingrad.ru http://forum.vingrad.ru 



--------------------------------------------------------------------------------

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

Это пример запуска консольных программ с передачей ей консольного ввода (как если бы он был введен с клавиатуры после запуска программы) и чтением консольного вывода. Таким способом можно запускать например стандартный виндовый 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; 
Взято из http://forum.sources.ru 







--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
XbiT
Дата 14.2.2006, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 65
Регистрация: 9.2.2006

Репутация: нет
Всего: 1



Спасибо, Romikgy. Теперь всё работает smile
PM MAIL   Вверх
Romikgy
Дата 15.2.2006, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 13
Всего: 146



XbiT, завжди велком smile


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0489 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.