I'm trying to execute cl.exe, and collect the output for use in my own app.
My problem is when I call ReadFile() on the handle, my program just hangs
indefinatly (probably because it can't read anything from the buffer). Here
is my code...am I don't something obviously wrong?
HANDLE hRead, hWrite;
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory( &si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.lpReserved2 = NULL;
si.wShowWindow = SW_HIDE;
SECURITY_ATTRIBUTES saP, saT, pa;
saT.bInheritHandle= TRUE; saP.bInheritHandle= TRUE; pa.bInheritHandle=
TRUE;
saT.nLength = sizeof(SECURITY_ATTRIBUTES); saP.nLength =
sizeof(SECURITY_ATTRIBUTES); pa.nLength = sizeof(SECURITY_ATTRIBUTES);
saT.lpSecurityDescriptor = NULL; saP.lpSecurityDescriptor = NULL;
pa.lpSecurityDescriptor = NULL;
CreatePipe(&hRead, &hWrite, &pa, 0);
si.hStdInput = hWrite;
si.hStdOutput = hRead;
si.hStdError = hRead;
sprintf(msg, "bin/cl %s", filename);
BOOL res = CreateProcess(NULL, msg, &saP, &saT, TRUE,
CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
if (res == FALSE)
{
MessageBox(g_hwnd, "CreateProcess Failed", "Error", MB_OK |
MB_ICONINFORMATION);
return FALSE;
}
output = (char *) malloc(10);
CloseHandle(hWrite);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
unsigned long bytesRead;
ReadFile(hRead, output, 10, &bytesRead, NULL);
CloseHandle(hRead);
[END CODE]
Thanks
-Fred
Yes.
>HANDLE hRead, hWrite;
>PROCESS_INFORMATION pi;
> STARTUPINFO si;
> ZeroMemory( &si, sizeof(STARTUPINFO));
> si.cb = sizeof(STARTUPINFO);
> si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
> si.lpReserved2 = NULL;
> si.wShowWindow = SW_HIDE;
>
>
> SECURITY_ATTRIBUTES saP, saT, pa;
> saT.bInheritHandle= TRUE; saP.bInheritHandle= TRUE; pa.bInheritHandle=
>TRUE;
> saT.nLength = sizeof(SECURITY_ATTRIBUTES); saP.nLength =
>sizeof(SECURITY_ATTRIBUTES); pa.nLength = sizeof(SECURITY_ATTRIBUTES);
> saT.lpSecurityDescriptor = NULL; saP.lpSecurityDescriptor = NULL;
>pa.lpSecurityDescriptor = NULL;
>
> CreatePipe(&hRead, &hWrite, &pa, 0);
>
> si.hStdInput = hWrite;
> si.hStdOutput = hRead;
> si.hStdError = hRead;
You attached the write-only end of the pipe to the program's *INPUT*,
and the read-only end to the program's *OUTPUT*. This won't work.
You actually need two pipes. One goes from you to the program, and the
other goes from the program to you. If the program doesn't read input,
you can dispense with the pipe that goes from you to it.
> sprintf(msg, "bin/cl %s", filename);
> BOOL res = CreateProcess(NULL, msg, &saP, &saT, TRUE,
>CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
> if (res == FALSE)
> {
> MessageBox(g_hwnd, "CreateProcess Failed", "Error", MB_OK |
>MB_ICONINFORMATION);
> return FALSE;
> }
> output = (char *) malloc(10);
>
> CloseHandle(hWrite);
> CloseHandle(pi.hThread);
> CloseHandle(pi.hProcess);
>
> unsigned long bytesRead;
> ReadFile(hRead, output, 10, &bytesRead, NULL);
>
> CloseHandle(hRead);
>
>[END CODE]
>
>Thanks
>-Fred
>
>
--
I am having the exact same problem, and I have created and attached my
pipes correctly (I believe). My child process isn't using stdin so I set
that pipe to INVALID_HANDLE_VALUE.
However, when I try to read from either the stdout or stderr pipe, the read
blocks.
Shoud I be using named pipes and possibly PeekNamedPipe? Any
recommendations?
HANDLE stdoutRead, stdoutWrite, stderrRead, stderrWrite;
CreatePipe( &stdoutRead, &stdoutWrite, NULL, 0 );
CreatePipe( &stderrRead, &stderrWrite, NULL, 0 );
STARTUPINFO si;
si.sb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES; // and any other flags you need
si.hStdInput = NULL; // I'd use NULL rather than INVALID_HANDLE_VALUE
si.hStdOutput = stdoutWrite; // use write ends
si.hStdError = stderrWrite;
...
CreateProcess( ... , &si , ... );
// Close the write-ends, as you don't need them anymore.
// The other process has its own handles on the pipe.
CloseHandle( stdoutWrite );
CloseHandle( stderrWrite );
// Use WaitForMultipleObjects to wait for input to be available
...
// read from the READ ends of the pipes
ReadFile( stdoutRead, ... );//or
ReadFile( stderrRead, ... );
>However, when I try to read from either the stdout or stderr pipe, the read
>blocks.
>
>Shoud I be using named pipes and possibly PeekNamedPipe? Any
>recommendations?
No need to use named pipes.
--
SteveR
Ah - this is probably what I was missing.
Question - how do I go about waiting for the pipes and the process handle?
Once the process handle is "done" is that when the pipes are also done?
Thanks!
>Question - how do I go about waiting for the pipes and the process handle?
>Once the process handle is "done" is that when the pipes are also done?
Okay, I tried this.
If I wait on the process to finish as well, sometimes it finishes before
the pipes are ready to read, and vise-versa. What's the trick to wait for
all 3, and not to deadlock if there is no data on one of the pipes?
If the other process is writing into the pipes, you may find it gets
held up waiting for you to read them. After it exits, once the pipes
are empty, they go to "end-of-file" mode, where they are always
signalled, so you need to stop waiting on them.
--
SteveR
The pipe should go signalled for "end-of-file" once the other process
completes, subject to two caveats:
1. If you don't close your copy of the write-end of the pipe immediately
after calling CreateProcess, this won't happen.
2. If you are using 9x, and you are spawning a true DOS app (as opposed
to a Win32 console app), it won't happen. See the MSDN Knowledge Base
article titled "Redirection issues on Windows 95" for information,
including how to work around it.
--
SteveR
Ah - I wasn't doing this. Didn't think it was necessary.
Once the pipe is in EOF mode, how do I know when there is no more data?
Would it return FALSE at this point, or just keep returning 0 for number of
bytes read.
Thanks for helping out a process newbie (I usually have no trouble with
graphics stuff!).
From the docs for ReadFile:
"If the anonymous write pipe handle has been closed and ReadFile
attempts to read using the corresponding anonymous read pipe handle, the
function returns FALSE and GetLastError returns ERROR_BROKEN_PIPE."
--
SteveR
It works!
Thanks Steve - looks like not closing the write end of the pipe was my main
problem. My pipe READING code was fine.
I appreciate all your assistance.
See Q58667 and/or Q190351 for details and examples on doing this.
Or, if you have the MSDN libraries, search for "redirect stdio console"
for several articles and examples.
--
+---------+----------------------------------+-----------------------------+
| Kenneth | kenbrody at spamcop.net | "The opinions expressed |
| J. | http://www.hvcomputer.com | herein are not necessarily |
| Brody | http://www.fptech.com | those of fP Technologies." |
+---------+----------------------------------+-----------------------------+