Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Проблема с чтением и выводом Pipe. Помогите разобраться.

35K
11 августа 2008 года
heor
17 / / 20.07.2008
Вот код:
Код:
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows, WinUtils;

function IsWinNT : boolean;  
var
 osv : OSVERSIONINFO;
begin
 FillChar(osv, SizeOf(osv), 0);
 osv.dwOSVersionInfoSize := sizeof(osv);
 GetVersionEx(osv);
 result := (osv.dwPlatformId = VER_PLATFORM_WIN32_NT);
end;

var
 newstdin, newstdout, read_stdout, write_stdin : THandle;
 tmpStdIn, tmpStdOut, tmpStdErr : THandle;
 si : STARTUPINFO;
 sa : SECURITY_ATTRIBUTES;
 sd : SECURITY_DESCRIPTOR;
 pi : PROCESS_INFORMATION;
 ph, tmp : THandle;
 exe : string;
 exit, bread, avail : cardinal;
 buf : array [0 .. 1023] of char;
 str : string;
 code : cardinal;
begin
 tmpStdIn:=GetStdHandle(STD_INPUT_HANDLE);
 tmpStdOut:=GetStdHandle(STD_OUTPUT_HANDLE);
 tmpStdErr:=GetStdHandle(STD_ERROR_HANDLE);

 if IsWinNT then        
 begin
  InitializeSecurityDescriptor(@sd, SECURITY_DESCRIPTOR_REVISION);
  SetSecurityDescriptorDacl(@sd, true, nil, false);
  sa.lpSecurityDescriptor := @sd;
 end
 else sa.lpSecurityDescriptor := nil;

 sa.nLength := sizeof(SECURITY_ATTRIBUTES);
 sa.bInheritHandle := true;      

 CreatePipe(newstdin, write_stdin, @sa, 0);  
 CreatePipe(read_stdout, newstdout, @sa, 0);  

 tmp := INVALID_HANDLE_VALUE;
 Ph:=GetCurrentProcess;
 DuplicateHandle(Ph, write_stdin, Ph, @tmp, 0, false, DUPLICATE_SAME_ACCESS);
 CloseHandle(write_stdin);
 write_stdin:=tmp;

 tmp := INVALID_HANDLE_VALUE;
 Ph:=GetCurrentProcess;
 DuplicateHandle(Ph, read_stdout, Ph, @tmp, 0, false, DUPLICATE_SAME_ACCESS);
 CloseHandle(read_stdout);
 read_stdout:=tmp;

 FillChar(si, SizeOf(si), 0);
 si.cb := SizeOf(si);
 GetStartupInfo(si);
 si.hStdOutput := GetStdHandle(STD_OUTPUT_HANDLE);
 si.hStdError := GetStdHandle(STD_ERROR_HANDLE);  
 si.hStdInput := GetStdHandle(STD_INPUT_HANDLE);  
 si.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
 si.wShowWindow := 1;
 si.hStdOutput := newstdout;
 si.hStdError := newstdout;  
 si.hStdInput := newstdin;    
 si.lpTitle := Pointer(exe);

 exe := 'c:\windows\system32\cmd.exe';

// tmpStdIn:=GetStdHandle(STD_INPUT_HANDLE);
// SetStdHandle(STD_INPUT_HANDLE, si.hStdInput);
// tmpStdOut:=GetStdHandle(STD_OUTPUT_HANDLE);
// SetStdHandle(STD_OUTPUT_HANDLE, si.hStdOutput);
// tmpStdErr:=GetStdHandle(STD_ERROR_HANDLE);
// SetStdHandle(STD_ERROR_HANDLE, si.hStdError);


 if not CreateProcess(PChar(exe), nil, nil, nil, true, CREATE_NEW_CONSOLE, nil, nil, si, pi) then
 begin
  code := GetLastError;
 end
 else
 begin
//  SetStdHandle(STD_INPUT_HANDLE, tmpStdIn);
//  SetStdHandle(STD_OUTPUT_HANDLE, tmpStdOut);
//  SetStdHandle(STD_ERROR_HANDLE, tmpStdErr);
  sleep(100);
  while true do      
  begin
   GetExitCodeProcess(pi.hProcess, exit);
   if (exit <> STILL_ACTIVE) then break;
   PeekNamedPipe(read_stdout, @buf, 1024, @bread, @avail, nil);
   while (bread <> 0) do
   begin
    fillChar(buf, 1024, 0);
    ReadFile(read_stdout, buf, 1024, bread, nil);
    SetString(str, PChar(String(@Buf)), bread);
    WriteFile(tmpStdOut, Pointer(str)^, length(str), bread, nil);
    //write(str);
    PeekNamedPipe(read_stdout, @buf, 1024, @bread, @avail, nil);
   end;
   fillChar(buf, 1024, 0);
//   readln(str);
   ReadFile(tmpStdIn, buf, 1024, bread, nil);
   SetString(str, PChar(String(@Buf)), bread);
   WriteFile(write_stdin, Pointer(str)^, bread, bread, nil);
//   ReadFile(read_stdout, buf, 1024, bread, nil);
   sleep(100);
   if str = 'exit' then break;
  end;
  TerminateProcess(pi.hProcess, 0);
 end;
end.


Работает почему то неверно. Запсукаю приложение:
Код:
Microsoft Windows XP [Версия 5.1.2600]
(С) Корпорация Майкрософт, 1985-2001.

W:\Prg\Delphi\Projects\ResourceMaker\2>fg
fg
"fg" не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.

W:\Prg\Delphi\Projects\ResourceMaker\2>fff
fff
"fff" не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.

W:\Prg\Delphi\Projects\ResourceMaker\2>

почему строчки "fff" и "fg" повторяються 2 раза. В командной строке мы такого не наблюдаем.
Если в коде
 
Код:
fillChar(buf, 1024, 0);
//   readln(str);
   ReadFile(tmpStdIn, buf, 1024, bread, nil);
   SetString(str, PChar(String(@Buf)), bread);
   WriteFile(write_stdin, Pointer(str)^, bread, bread, nil);
//   ReadFile(read_stdout, buf, 1024, bread, nil);
   sleep(100);
   if str = 'exit' then break;

раскоментировать ReadFile(read_stdout, buf, 1024, bread, nil); то все становиться норм. Но это не выход. А что если он прочитает, не тот символ, к-й мы отправили, а уже ответ, как мы узнаем об этом?
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог