PDA

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



psix
31.10.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
02.11.2004, 03:17
http://ssz.by.ru/programming/cpp/pipes.htm

Naeel Maqsudov
02.11.2004, 03:19
То был СИ-шный пример, а вот Дельфи: http://e-dok.narod.ru/delphi/question1/os/os-018.html

psix
16.11.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(f exit=STILL_ACTIVE)and(WriteBuff<>'exit'))do
begin
readln(WriteBuff);
WriteFile(wstdin,WriteBuff,1,BytesCount,nil);
repeat
WasOK:=ReadFile(rstdout,ReadBuff,255,BytesCount,ni l);//******

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
18.11.2004, 15:24
...на первом круге вложенного цикла...
то есть на втором :oops:

psix
29.11.2004, 22:12
помогите, пожалуйста
не знаю, что делать

Eugie
30.11.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
07.03.2008, 13:01
На месте, помеченном звездочками программа повисает на первом круге вложенного
цикла repeat.(можно добавить там writeln(1) и убедиться в этом). почему это происходит и как поправить дело?

repeat
WasOK:=ReadFile(rstdout,ReadBuff,255,BytesCount,ni l);//******
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 := #0;
R := R + chBuf;
Application.ProcessMessages;
end;
WasOK := False;
end;
until WasOK ;

[B]Удачи! :D