From: Manu <ma...@wa...> - 2003-12-26 15:30:04
|
Alberto Luaces wrote: > Hello, I'm having problems when using win32 pipes. I'm using them to run > programs as 'sed' or 'gawk' and read the results from my program. The code: > > #include <stdio.h> > #include <windows.h> > > HANDLE OpenPipe(char *,HANDLE *); > void ClosePipe(void); > > int i=0; > char buffer[1024]; > > int main(){ > DWORD read; > HANDLE hProcess, hRead; > > hRead=OpenPipe("gawk '/^[0-9\\-]/{print $1,$2}' > at020304_No3_n2.txt",&hProcess); > file://WaitForSingleObject(hProcess,INFINITE); > > do{ > ReadFile(hRead,buffer,sizeof(buffer)-1,&read,0); > > printf("Size of buffer - %d\n",sizeof(buffer)); > printf("Bytes read - %i\nTimes - %i\n",read,i++); > > buffer[read]=0; /* Zero-terminated string */ > > puts(buffer); > }while (read==sizeof(buffer)-1); > > ClosePipe(); > > return 0; > > } > > My OpenPipe() and ClosePipe() functions are implemented with CreatePipe() > and CreateProcess(), feeding the pipe with handle to standard output of > the child process and returning the read handle and the process handle. > > At first I placed the WaitForSingleObject(hProcess,INFINITE) call, but it > never returned, I wonder why. From what I read in the documentation, > ReadFile() waits until something is written to the pipe, so I didn't place > another WaitForSingleObject(hRead,INFINITE) call. > > Am I doing anything wrong? How can I know if the last read size fits > exactly in the buffer or there is more data to read? I tried at first > something like this: > > do{ > /*read the pipe*/ > }while(read!=0); > > but ReadFile() never returned as the pipe was empty from the last call. Well, I can share a bit of my experience, this is how I proceed in Visual-MinGW: ------ * src/libtemp/process/childprs.cpp (CChildProcess::Run) // simple process without IO redirection. if (!_redirect){ // wait for this process. ::WaitForSingleObject(pi.hProcess, INFINITE); ::GetExitCodeProcess(pi.hProcess, &exitCode); // process with IO redirection. }else{ // perform IO. for (;;){ Sleep(100L); // read std out. _outPipe.Read(_outBuffer); ProcessStdOut(); // read std error. _errPipe.Read(_errBuffer); ProcessStdErr(); // still running ? ::GetExitCodeProcess(pi.hProcess, &exitCode); if (exitCode != STILL_ACTIVE){ break; }else if (_abort){ ::TerminateProcess(pi.hProcess, 1); break; } } } ----- * src/libtemp/process/pipe.cpp (CPipe::Read) int CPipe::Read(COutBuffer &buffer){ /* Read all available bytes from the pipe into a buffer, then output * each '\n' terminated line. Non-terminated ones remains first in buffer, * waiting for more bytes. */ if (!hRead) return 0; // get the total number of bytes available from the pipe. DWORD avail = 0; while (_peek(&avail)){ DWORD bytes_read = 0; // seek the buffer, read all bytes, update the buffer's state. if (!_read(buffer, avail, &bytes_read)) return 0; return 0; } // nothing to read. return 0; } CPipe::_peek() calls PeekNamedPipe to know if we have something to read, then CPipe::_read() fills the output buffer (COutBuffer). You can freely use the code in /libtemp, it is currently GPL'ed, but it will be moved into WinUI library soon, then it will be switched to public domain. As the copyright holder, I give you acknowledgement to use it in your app, in case it is helpfull. http://cvs.sourceforge.net/viewcvs.py/visual-mingw/visual-mingw/src/libtemp/ A Google search with "PeekNamedPipe", "ReadFile", etc... will give you much more inputs. Enjoy! Manu. |