Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Перенаправление ввода и вывода


Автор: Nobodyx 26.3.2005, 21:52
Намереваюсь сделать удалённую коммандную строку .(Bind Shell) Сама передача по сети не проблема(через winsock). Подскажите, пожалуйста, как организовать обмен данными с cmd.exe. Необходим не просто одиночный запуск cmd.exe с передачей параметров и получением вывода, а именно непрерывный обмен данными.

Автор: _hunter 28.3.2005, 15:02
что ты подразумеваеш под непрерывным обменом? ибо передача ввода и получение вывода это и есть непрерывный обмен...

Автор: Snowy 28.3.2005, 15:55
Это возможно, но слишком проблематично.
Легче будет каждый раз вызывать ComSpec с ключем /C, чем эмулировать ему нажатие клавиш.

Автор: Гость_Ник 5.4.2005, 09:04
Меня тоже интересует эта тема. Для того, чтобы было понятно, напишу на примере, что я хочу. Например запускаем telnet.exe, вводим open 127.0.0.1 80 (передача ввода) и получаем вывод с консоли (передача вывода). И так в интерактивном режиме. Нашел кое-что в базе знаний:
Код

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

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



Однако во-первых вылезает несколько ошибок (но я их поправил почти все, несколько ошибок типов и как мне кажется недописано кое-где =, например в " if ProcInf.hProcess 0 then ". Однако, что такое iWAIT_OBJECT_0 я так и не смог понять smile. Может кто скажет, в чем проблема или подкинет рабочий исходничек smile.

Автор: Nobodyx 7.4.2005, 06:49
Cм.
http://forum.sources.ru/index.php?showtopic=89005

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)