Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.09.03;
Скачать: CL | DM;

Вниз

Перенаправление stdout & stdin консольного приложения   Найти похожие ветки 

 
pasha_golub ©   (2006-07-20 13:27) [0]

Моя программа - фронтэнд для консоли. Задача: запустить с нужными параметрами, передать пароль и вернуть вывод.

Есть код, который работает с предыдущей версией сторонней консольной программы, но не работает с последней версией. Хотя видимых различий не нашел.

Процесс запускается. Выводит "Password:" и ждет ввода. Но в моей программе исполнение ждет чтения:

          // read block of data
          WasOK := ReadFile( StdOutPipeRead, Buffer, 1023, BytesRead, nil );


Подскажите, кто что сможет, пожалуйста.


Function GetConsoleOutput( CommandLine, Pass, ResName: String; var ResultCode: Cardinal ): String;
var
   //process launch and in/out stuff
   StdOutPipeRead,
   StdOutPipeWrite,
   StdInPipeRead,
   StdInPipeWrite: THandle;
   SA            : TSecurityAttributes;
   SI            : TStartupInfo;
   PI            : TProcessInformation;
   WasOK         : Boolean;
   Buffer        : array[0..1023] of Char;
   BytesRead     : Cardinal;
   Line          : String;
   Written       : DWORD;
   Passed        : boolean;
   nb, i: Cardinal;
   RS: TResourceStream;
Begin
  With SA do
  Begin
     nLength := SizeOf( SA );
     bInheritHandle := True;
     lpSecurityDescriptor := nil;
  end;
  CreatePipe( StdOutPipeRead,
              StdOutPipeWrite,
              @SA,
              0           );
  CreatePipe( StdInPipeRead,
              StdInPipeWrite,
              @SA,
              0           );
  try
   with SI do
   Begin
      FillChar( SI, SizeOf( SI ), 0 );
      cb := SizeOf( SI );
      dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
      wShowWindow := SW_HIDE or SW_SHOWMINNOACTIVE;
      hStdInput := StdInPipeRead;
      hStdOutput := StdOutPipeWrite;
      hStdError := StdOutPipeWrite;
   end;
   Passed := false;

   RS := TResourceStream.Create(HInstance,ResName,Pchar("EXEFILE"));
    try
   RS.SaveToFile(ResName+".exe");
   CommandLine := Format(CommandLine,[ResName+".exe"]);
   WasOK := CreateProcess( nil,
                     PChar(Commandline),
                     nil,
                     nil,
                     True,
                     0,
                     nil,
                     nil,
                     SI,
                     PI );
    finally
   RS.Free;
    end;

   CloseHandle( StdOutPipeWrite );
   CloseHandle( StdInPipeRead );
   if not WasOK then
    raise Exception.Create( "Can""t start process: "#10#13 +
            CommandLine )
   else
     try
       Line := "";
       Repeat
          // read block of data
          WasOK := ReadFile( StdOutPipeRead, Buffer, 1023, BytesRead, nil );
          // is there anything to read
          if BytesRead > 0 then
          Begin
             Buffer[BytesRead] := #0;
             // add buffer
             Line := Line + Buffer;
          end;
         If not Passed AND
            (Pos("PASSWORD:",AnsiUpperCase(Line)) > 0) then
           begin
             Line := StringReplace(Line,"password:","",[rfIgnoreCase]);
             Pass := Pass + #13#10; //add carriage return
             WasOk := WriteFile(StdinPipeWrite,Pass[1],length(Pass),Written,nil);
             Passed := true; //passed authorization
           end;
       Until not WasOK or ( BytesRead = 0 );
       // wait console
       WaitForSingleObject( pi.hProcess, INFINITE );
       ResultCode := 0;
       GetExitCodeProcess( pi.hProcess, ResultCode );
     finally
       // close descriptors
       CloseHandle( PI.hThread );
       CloseHandle( pi.hProcess );
     end;
  finally
    Result := Line;
    CloseHandle( StdOutPipeRead );
    CloseHandle( StdInPipeWrite );
    SysUtils.DeleteFile(ResName+".exe");
end;
end;


 
pasha_golub ©   (2006-07-20 13:29) [1]

Ой, мама, промахнулся разделом. Извините.


 
Slym ©   (2006-07-20 13:45) [2]

TOverlapped тебе в подарок


 
pasha_golub ©   (2006-07-20 14:29) [3]


> Slym ©   (20.07.06 13:45) [2]
>
> TOverlapped тебе в подарок
>

Спасибо за подарок. Деталей бы хотелось. Их есть у вас?


 
Игорь Шевченко ©   (2006-07-20 14:35) [4]


> Есть код, который работает с предыдущей версией сторонней
> консольной программы, но не работает с последней версией.
>  Хотя видимых различий не нашел.


Я извиняюсь, а новая версия точно работает через стандартные Handles, а не делает внутри себя что-то вроде AllocConsole и т.п. ?


 
pasha_golub ©   (2006-07-20 15:55) [5]


> Игорь Шевченко ©   (20.07.06 14:35) [4]


>
> Я извиняюсь, а новая версия точно работает через стандартные
> Handles, а не делает внутри себя что-то вроде AllocConsole
> и т.п. ?
>

Думал об этом. Попробую узнать у авторов. Спасибо


 
Slym ©   (2006-07-21 04:43) [6]

pasha_golub ©   (20.07.06 14:29) [3]
Деталей бы хотелось. Их есть у вас?

Чтение с таймаутом, выдрано из Scktcomp.pas, но применимо для файлов и пр. хендлов:
while true do
Читаешь StdIn(100мсеков)
пишешь StdOut
procedure ReadBuffer(ASocket:TSocket;var Buffer;Count:Longint;ATimeout:Longint=0);
var
 Overlapped: TOverlapped;
 ErrorCode,Result: Integer;
begin
 if ATimeout=0 then ATimeout:=DefTimeout;
 FillChar(OVerlapped,SizeOf(Overlapped),0);
 Overlapped.hEvent:=CreateEvent(nil,True,False,"");
 try
   if not ReadFile(ASocket, Buffer, Count, DWORD(Result),
     @Overlapped) and (GetLastError <> ERROR_IO_PENDING) then
   begin
     ErrorCode := GetLastError;
     raise ESocketError.CreateResFmt(@sSocketIOError, [sSocketRead, ErrorCode,
       SysErrorMessage(ErrorCode)]);
   end;
   if WaitForSingleObject(Overlapped.hEvent, ATimeout)<>WAIT_OBJECT_0 then
     Result := 0
   else
     GetOverlappedResult(ASocket, Overlapped, DWORD(Result), False);
 finally
   CloseHandle(Overlapped.hEvent);
 end;
end;

procedure WriteBuffer(ASocket:TSocket; const Buffer; Count: Longint;ATimeout:Longint=0);
var
 Overlapped: TOverlapped;
 ErrorCode,Result: Integer;
begin
 if ATimeout=0 then ATimeout:=DefTimeout;
 FillChar(OVerlapped,SizeOf(Overlapped),0);
 Overlapped.hEvent:=CreateEvent(nil,True,False,"");
 try
   if not WriteFile(ASocket, Buffer, Count, DWORD(Result),
     @Overlapped) and (GetLastError <> ERROR_IO_PENDING) then
   begin
     ErrorCode := GetLastError;
     raise ESocketError.CreateResFmt(@sSocketIOError, [sSocketWrite, ErrorCode,
       SysErrorMessage(ErrorCode)]);
   end;
   if WaitForSingleObject(Overlapped.hEvent, ATimeout)<>WAIT_OBJECT_0 then
     Result := 0
   else GetOverlappedResult(ASocket, Overlapped, DWORD(Result), False);
 finally
   CloseHandle(Overlapped.hEvent);
 end;
end;


 
RUNaum ©   (2006-07-21 07:19) [7]

Игорь Шевченко ©   (20.07.06 14:35) [4]
кстати, а как быть в случаях подобных AllocConsole, к примеру?


 
Игорь Шевченко ©   (2006-07-21 10:16) [8]

RUNaum ©   (21.07.06 07:19) [7]

А вроде никак...


 
pasha_golub ©   (2006-07-21 17:58) [9]


> Slym ©   (21.07.06 04:43) [6]

Спасибо попробую.

Раскопал библиотеку wxWidgets. Реализовано вроде так же как и у меня, но с некоторыми отстпуплениями. Кому интересно могу сюда выложить код.


 
pasha_golub ©   (2006-07-24 12:14) [10]


> Slym ©   (21.07.06 04:43) [6]

В хелпе написано:

Parameters

hFile

Identifies the file, named pipe, or communications device.


У меня anonymous pipe. Будет ли пригоден данный метод?


 
pasha_golub ©   (2006-07-24 12:30) [11]

Судя по всему, что нет. Вылетает ошибка.



Страницы: 1 вся ветка

Текущий архив: 2006.09.03;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.052 c
1-1152376503
Baitur
2006-07-08 20:35
2006.09.03
Unicode


2-1155278172
rebroff
2006-08-11 10:36
2006.09.03
Триггер на добавление записи в дочернюю таблицу


3-1151004540
Krants
2006-06-22 23:29
2006.09.03
Хроника БД Access


2-1155371002
SerJaNT
2006-08-12 12:23
2006.09.03
Колесо прокрутки


15-1155304386
evvcom
2006-08-11 17:53
2006.09.03
Видали картинки?