From: David Crow on 29 Oct 2009 11:50 I've created a console window with redirected stdin and stdout. I send that window a command (e.g., dir), and then read the results from that window. This works intermittently. The command I send governs the "timing" of my code. For example: CreateProcess("cmd.exe", ...); // write the command DWORD dw; WriteFile(write_stdin, cmd, cmd.GetLength(), &dw, NULL); // wait for something to show up do { PeekNamedPipe(read_stdout, NULL, 0, NULL, &dw, NULL); } while (dw == 0); // read until no more do { ReadFile(read_stdout, buf, 31, &read, NULL); PeekNamedPipe(read_stdout, NULL, 0, NULL, &dw, NULL); } while (dw != 0); If I change 31 to 32, it stops working when "dir" is the command. If the command is "chkdsk /?" instead, I use 5. I understand that ReadFile() will block until that number of bytes have been read. Ultimately I'd just wait until the command was finished (and use PeekNamedPipe() to know how much to read), but I don't know how to check that, and the console-window buffer is only so big. Any suggestions? Thanks. - DC
From: Tamas Demjen on 29 Oct 2009 16:06 David Crow wrote: > I understand that ReadFile() will block until that number of bytes have been > read. It doesn't necessarily have to block, you can opt to use overlapped I/O. > Ultimately I'd just wait until the command was finished (and use > PeekNamedPipe() to know how much to read), but I don't know how to check > that PeekNamedPipe can return the number of bytes available on the pipe: DWORD bytesAvailable = 0; if(PeekNamedPipe(pipeHandle, NULL, 0, NULL, &bytesAvailable, NULL)) ... Just read bytesAvailable number of bytes. It's not going to block this way, because you're not reading more than what's already there. Tom
From: David Crow on 29 Oct 2009 16:45 I'm currently not using overlapped I/O. From my understanding of it, which is not great, it was not needed. Even if I changed the loop to be: // wait for something to show up after sending command do { PeekNamedPipe(read_stdout, NULL, 0, NULL, &dw, NULL); } while (dw == 0); // read until no more do { ReadFile(read_stdout, buf, dw, &read, NULL); PeekNamedPipe(read_stdout, NULL, 0, NULL, &dw, NULL); } while (dw != 0); there is a slight delay after the command is issued but before it starts outputting anything. This results in "dw" being 0 and the second while() loop exiting after one iteration. The call to ReadFile() will read once getting the characters that show up when the command prompt window is opened plus the characters that are in the command (e.g., chkdsk, ipconfig, dir). I can put a 1-second delay in between the two while() loops but that does not seem right. "Tamas Demjen" <tdemjen(a)yahoo.com> wrote in message news:%23EV6HNNWKHA.4816(a)TK2MSFTNGP06.phx.gbl... > > PeekNamedPipe can return the number of bytes available on the pipe: > > DWORD bytesAvailable = 0; > if(PeekNamedPipe(pipeHandle, NULL, 0, NULL, &bytesAvailable, NULL)) > ... > > Just read bytesAvailable number of bytes. It's not going to block > this way, because you're not reading more than what's already there. > > Tom
From: Tamas Demjen on 30 Oct 2009 20:46 David Crow wrote: > // wait for something to show up after sending command > do > { > PeekNamedPipe(read_stdout, NULL, 0, NULL, &dw, NULL); > } while (dw == 0); > > // read until no more > do > { > ReadFile(read_stdout, buf, dw, &read, NULL); > PeekNamedPipe(read_stdout, NULL, 0, NULL, &dw, NULL); > } while (dw != 0); You have to repeatedly call PeekNamedePipe until the pipe has something to read. You're doing a ReadFile, followed by an immediate peek. You're likely to have an empty pipe right after reading. So you have to keep peeking until your process exits. I was thinking of something like this (with more error handling added): bool stillRunning = true; while(stillRunning) { DWORD bytesAvailable = 0; do { DWORD exitCode = 0; // Check if the process is still running GetExitCodeProcess(hProcess, &exitCode); if(exitCode != STILL_ACTIVE) stillRunning = false; PeekNamedPipe(hPipe, NULL, 0, NULL, &bytesAvailable, NULL); } while(bytesAvailable == 0 && stillRuning); ReadFile(...); } You can add some sleep between peeks to avoid too much CPU utilization: WaitForSingleObject(hProcess, 100); Perhaps it would be better to do overlapped I/O in a thread with WaitForMultipleObjects, and wait until either the process finishes, or the overlapped I/O triggers. Then you don't have to do polling. Tom
|
Pages: 1 Prev: Memory acces completely optimized away Next: What is the share mode for fopen()? |