ПАЙПЫ. помогите разобраться на примере моей программы.

Модераторы: Duncon, Naeel Maqsudov, Хыиуду, Игорь Акопян

Ответить
psix
Сообщения: 52
Зарегистрирован: 29 июл 2004, 13:53
Откуда: Россия, Москва
Контактная информация:

31 окт 2004, 13:18

Есть такая программа:

Код: Выделить всё

program my;
{$APPTYPE CONSOLE}
var s:string;
begin
readln(s);
if s='hello'then writeln('"hello" Acepted')
else writeln('You has enter somethink another.');
readln;
end.
Нужно написать вторую программу, которая запускает ее, первую, шлет ей строку 'hello' и записывает ответ в текстовый файл.
Желательно, чтобы программа была как можно более уневерсальной.
Помогите, пожалуйста.
Аватара пользователя
Naeel Maqsudov
Сообщения: 2551
Зарегистрирован: 20 фев 2004, 19:17
Откуда: Moscow, Russia
Контактная информация:

02 ноя 2004, 03:19

То был СИ-шный пример, а вот Дельфи: http://e-dok.narod.ru/delphi/question1/os/os-018.html
psix
Сообщения: 52
Зарегистрирован: 29 июл 2004, 13:53
Откуда: Россия, Москва
Контактная информация:

16 ноя 2004, 21:47

помогите, пожалуйста
Вот код программы:

Код: Выделить всё

program pipe;

{$APPTYPE CONSOLE}

uses Windows,
     SysUtils;

var SA:TSecurityAttributes;
    SI:TStartupInfo;
    PI:TProcessInformation;
    fexit,cstdin,wstdin,rstdout,cstdout:THandle;
    WasOK:Boolean;
    ReadBuff,WriteBuff:array[0..255]of Char;
    BytesCount:Cardinal;
begin

with SA do
begin
  nLength:=SizeOf(SA);
  bInheritHandle:=True;
  lpSecurityDescriptor:=nil;
end;

if not CreatePipe(cstdin,wstdin,@SA,0) then exit;
if not CreatePipe(rstdout,cstdout,@SA,0) then exit;

GetStartupInfo(SI);

try

  with SI do
  begin
    dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
    wShowWindow:=SW_HIDE;
    hStdOutput:=cstdout;
    hStdError:=cstdout;
    hStdInput:=cstdin;
  end;


  WasOK:=CreateProcess(nil,PChar('c:\projects\delphi\testprog.exe'),nil,nil,true,CREATE_NEW_CONSOLE{0},nil,nil,SI,PI);

  if not WasOK then exit
  else
    try

    while((GetExitCodeProcess(PI.hProcess,fexit))and(fexit=STILL_ACTIVE)and(WriteBuff<>'exit'))do
    begin
    readln(WriteBuff);
    WriteFile(wstdin,WriteBuff,1,BytesCount,nil);
      repeat
        WasOK:=ReadFile(rstdout,ReadBuff,255,BytesCount,nil);//******

        if BytesCount > 0 then
        begin
          write(ReadBuff);
        end;
      until {not WasOK or}(BytesCount<255);
      sleep(1);
    end;
     readln;
    WaitForSingleObject(PI.hProcess,INFINITE);
    finally

    CloseHandle(PI.hThread);
    CloseHandle(PI.hProcess);
    end;

finally
CloseHandle(fexit);
CloseHandle(cstdin);
CloseHandle(wstdin);
CloseHandle(rstdout);
CloseHandle(cstdout);
end;

end.
На месте, помеченном звездочками программа повисает на первом круге вложенного цикла repeat.(можно добавить там writeln(1) и убедиться в этом). почему это происходит и как поправить дело?
Возможно, будут еще какие советы по поводу этого кода?
psix
Сообщения: 52
Зарегистрирован: 29 июл 2004, 13:53
Откуда: Россия, Москва
Контактная информация:

18 ноя 2004, 15:24

...на первом круге вложенного цикла...
то есть на втором :o ops:
psix
Сообщения: 52
Зарегистрирован: 29 июл 2004, 13:53
Откуда: Россия, Москва
Контактная информация:

29 ноя 2004, 22:12

помогите, пожалуйста
не знаю, что делать
Eugie
Сообщения: 707
Зарегистрирован: 17 фев 2004, 23:59
Откуда: SPb

30 ноя 2004, 13:07

Вот пример из MSDN, просто перепиши на Delhpi

Главный процесс:

Код: Выделить всё

#include <stdio.h> 
#include <windows.h> 
 
#define BUFSIZE 4096 
 
HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, 
   hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup, 
   hInputFile, hSaveStdin, hSaveStdout; 
 
BOOL CreateChildProcess(VOID); 
VOID WriteToPipe(VOID); 
VOID ReadFromPipe(VOID); 
VOID ErrorExit(LPTSTR); 
VOID ErrMsg(LPTSTR, BOOL); 
 
DWORD main(int argc, char *argv[]) 
{ 
   SECURITY_ATTRIBUTES saAttr; 
   BOOL fSuccess; 
 
// Set the bInheritHandle flag so pipe handles are inherited. 
 
   saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
   saAttr.bInheritHandle = TRUE; 
   saAttr.lpSecurityDescriptor = NULL; 
 
   // The steps for redirecting child process's STDOUT: 
   //     1. Save current STDOUT, to be restored later. 
   //     2. Create anonymous pipe to be STDOUT for child process. 
   //     3. Set STDOUT of the parent process to be write handle to 
   //        the pipe, so it is inherited by the child process. 
   //     4. Create a noninheritable duplicate of the read handle and
   //        close the inheritable read handle. 
 
// Save the handle to the current STDOUT. 
 
   hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
 
// Create a pipe for the child process's STDOUT. 
 
   if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) 
      ErrorExit("Stdout pipe creation failed\n"); 
 
// Set a write handle to the pipe to be STDOUT. 
 
   if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) 
      ErrorExit("Redirecting STDOUT failed"); 
 
// Create noninheritable read handle and close the inheritable read 
// handle. 

    fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
        GetCurrentProcess(), &hChildStdoutRdDup , 0,
        FALSE,
        DUPLICATE_SAME_ACCESS);
    if( !fSuccess )
        ErrorExit("DuplicateHandle failed");
    CloseHandle(hChildStdoutRd);

   // The steps for redirecting child process's STDIN: 
   //     1.  Save current STDIN, to be restored later. 
   //     2.  Create anonymous pipe to be STDIN for child process. 
   //     3.  Set STDIN of the parent to be the read handle to the 
   //         pipe, so it is inherited by the child process. 
   //     4.  Create a noninheritable duplicate of the write handle, 
   //         and close the inheritable write handle. 
 
// Save the handle to the current STDIN. 
 
   hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); 
 
// Create a pipe for the child process's STDIN. 
 
   if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) 
      ErrorExit("Stdin pipe creation failed\n"); 
 
// Set a read handle to the pipe to be STDIN. 
 
   if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) 
      ErrorExit("Redirecting Stdin failed"); 
 
// Duplicate the write handle to the pipe so it is not inherited. 
 
   fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, 
      GetCurrentProcess(), &hChildStdinWrDup, 0, 
      FALSE,                  // not inherited 
      DUPLICATE_SAME_ACCESS); 
   if (! fSuccess) 
      ErrorExit("DuplicateHandle failed"); 
 
   CloseHandle(hChildStdinWr); 
 
// Now create the child process. 
 
   if (! CreateChildProcess()) 
      ErrorExit("Create process failed"); 
 
// After process creation, restore the saved STDIN and STDOUT. 
 
   if (! SetStdHandle(STD_INPUT_HANDLE, hSaveStdin)) 
      ErrorExit("Re-redirecting Stdin failed\n"); 
 
   if (! SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) 
      ErrorExit("Re-redirecting Stdout failed\n"); 
 
// Get a handle to the parent's input file. 
 
   if (argc > 1) 
      hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, 
         OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); 
   else 
      hInputFile = hSaveStdin; 
 
   if (hInputFile == INVALID_HANDLE_VALUE) 
      ErrorExit("no input file\n"); 
 
// Write to pipe that is the standard input for a child process. 
 
   WriteToPipe(); 
 
// Read from pipe that is the standard output for child process. 
 
   ReadFromPipe(); 
 
   return 0; 
} 
 
BOOL CreateChildProcess() 
{ 
   PROCESS_INFORMATION piProcInfo; 
   STARTUPINFO siStartInfo; 
 
// Set up members of the PROCESS_INFORMATION structure. 
 
   ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
 
// Set up members of the STARTUPINFO structure. 
 
   ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
   siStartInfo.cb = sizeof(STARTUPINFO); 
 
// Create the child process. 
 
   return CreateProcess(NULL, 
      "child",       // command line 
      NULL,          // process security attributes 
      NULL,          // primary thread security attributes 
      TRUE,          // handles are inherited 
      0,             // creation flags 
      NULL,          // use parent's environment 
      NULL,          // use parent's current directory 
      &siStartInfo,  // STARTUPINFO pointer 
      &piProcInfo);  // receives PROCESS_INFORMATION 
}
 
VOID WriteToPipe(VOID) 
{ 
   DWORD dwRead, dwWritten; 
   CHAR chBuf[BUFSIZE]; 
 
// Read from a file and write its contents to a pipe. 
 
   for (;;) 
   { 
      if (! ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, NULL) || 
         dwRead == 0) break; 
      if (! WriteFile(hChildStdinWrDup, chBuf, dwRead, 
         &dwWritten, NULL)) break; 
   } 
 
// Close the pipe handle so the child process stops reading. 
 
   if (! CloseHandle(hChildStdinWrDup)) 
      ErrorExit("Close pipe failed\n"); 
} 
 
VOID ReadFromPipe(VOID) 
{ 
   DWORD dwRead, dwWritten; 
   CHAR chBuf[BUFSIZE]; 
   HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 

// Close the write end of the pipe before reading from the 
// read end of the pipe. 
 
   if (!CloseHandle(hChildStdoutWr)) 
      ErrorExit("Closing handle failed"); 
 
// Read output from the child process, and write to parent's STDOUT. 
 
   for (;;) 
   { 
      if( !ReadFile( hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead, 
         NULL) || dwRead == 0) break; 
      if (! WriteFile(hSaveStdout, chBuf, dwRead, &dwWritten, NULL)) 
         break; 
   } 
} 
 
VOID ErrorExit (LPTSTR lpszMessage) 
{ 
   fprintf(stderr, "%s\n", lpszMessage); 
   ExitProcess(0); 
}
Дочерний процесс:

Код: Выделить всё

#include <windows.h> 
#define BUFSIZE 4096 
 
VOID main(VOID) 
{ 
   CHAR chBuf[BUFSIZE]; 
   DWORD dwRead, dwWritten; 
   HANDLE hStdin, hStdout; 
   BOOL fSuccess; 
 
   hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
   hStdin = GetStdHandle(STD_INPUT_HANDLE); 
   if ((hStdout == INVALID_HANDLE_VALUE) || 
      (hStdin == INVALID_HANDLE_VALUE)) 
      ExitProcess(1); 
 
   for (;;) 
   { 
   // Read from standard input. 
      fSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL); 
      if (! fSuccess || dwRead == 0) 
         break; 
 
   // Write to standard output. 
      fSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL); 
      if (! fSuccess) 
         break; 
   } 
} 
eFanchik
Сообщения: 1
Зарегистрирован: 07 мар 2008, 12:48

07 мар 2008, 13:01

На месте, помеченном звездочками программа повисает на первом круге вложенного
цикла repeat.(можно добавить там writeln(1) и убедиться в этом). почему это происходит и как поправить дело?

repeat
WasOK:=ReadFile(rstdout,ReadBuff,255,BytesCount,nil);//******
if BytesCount > 0 then
begin
write(ReadBuff);
end;
until {not WasOK or}(BytesCount<255);


Столкнулся с той же порблемой! 80% примеров просмотренных мною дохлые. Пишут умники, которым лень проанализировать код. Решил проблему так:

repeat
WasOK := True;
if PeekNamedPipe(hOutputRead, @chBuf, SizeOF(chBuf), @BytesRead, @BytesAvail, nil)
and (BytesAvail > 0) then
begin
if not ReadFile(hOutputRead, chBuf, SizeOf(chBuf), BytesRead, nil)
then WinError('Ошибка канала STDOUT : ');
if BytesRead > 0 then
begin
chBuf[BytesRead] := #0;
R := R + chBuf;
Application.ProcessMessages;
end;
WasOK := False;
end;
until WasOK ;

Удачи! :D
Ответить