Форум: "Основная";
Текущий архив: 2006.09.03;
Скачать: [xml.tar.bz2];
ВнизПеренаправление 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мсеков)
пишешь StdOutprocedure 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;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.036 c