http://www.codeguru.com/misc/RedirectOutputToPipe.shtml
This article was contributed by Xinhai Kang.
Environment: Visual C++ 6.0 SP2, Windows NT 4.0 SP4
I have the thought of redirecting output of WIN32 console programs to a pipe or a file long ago, but I don't know to do at all at first, finally I searched through Microsoft MSDN and found a way, the code pasted below was copied from MSDN sample code except some changes in function CreateChildProcess(), where I stressed in the code.
In the demo source, I redirect the stdout of CMD.exe to a pipe and start a thread to read from this pipe, then all that CMD.EXE output was redirected to the pipe where I am reading.
// 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) )
{
TRACE0( _T("Stdout pipe creation failed\n") );
return FALSE;
}
// Set a write handle to the pipe to be STDOUT.
if( !SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) )
{
TRACE0( _T("Redirecting STDOUT failed\n") );
return FALSE;
}
// 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) )
{
TRACE0( _T("Stdin pipe creation failed\n") );
return FALSE;
}
// Set a read handle to the pipe to be STDIN.
if( !SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd) )
{
TRACE0( _T("Redirecting Stdin failed\n") );
return FALSE;
}
// 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 )
{
TRACE0( _T("DuplicateHandle failed\n") );
return FALSE;
}
CloseHandle(hChildStdinWr);
// Set up members of STARTUPINFO structure.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
/////////////////////////////////////////
/*
Note here the
dwFlags should be STARTF_USESTDHANDLES, which is descripted in WIN32 API
document, but this was
omitted in MSDN sample
*/
siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdError = hChildStdoutWr;
///////////////////////////////////////////////////
TCHAR shellCmd[_MAX_PATH];
if( !GetEnvironmentVariable(_T("ComSpec"), shellCmd, _MAX_PATH) )
return FALSE;
#ifdef _UNICODE
_tcscat( shellCmd, _T(" /U") );
#else
_tcscat( shellCmd, _T(" /A") );
#endif
// Create the child process.
BOOL ret = CreateProcess( NULL,
shellCmd, // applicatin name
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
DETACHED_PROCESS, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if( ret )
dwProcessId = piProcInfo.dwProcessId;
return ret;
}
Download source - 5 KB
Date Last Updated: April 4, 1999
Comments:
pop up a console window - iop (2003/02/28)
Redirect Output of CMD.EXE to a Pipe - Cheng Chao (2002/08/27)
Not coming out of Thread's for loop - shimsha_r (2001/01/16)
sending commands to stdin ? - Johnny J (2000/10/23)
not included all the header files !!!!! - simran bir singh (2000/05/03)
Do you know how to achieve the same... asynchronously? - Jason Hattingh (1999/07/06)
Works for Win9x and WinNT now - Uwe Kotyczka (1999/07/05)
It would be great if you could provide the demo project - Xiaojian Liu (1999/07/05)
WHERE IS THE GURUEDITOR.H ? HOW CAN I COMPILE IT OK? - KONG (1999/06/14)
Class CExecute - Xinhai Kang (1999/04/08)
Under Win9x - Yangghi Min (1999/04/07)
Win95 can be done - John Young (1999/04/07)
Win95 too ! - Shark (1999/04/06)
Win95 too? - Troels (1999/04/05)
Add Comment