Redirect Output of CMD.EXE to a Pipe | CodeGuru

Redirect Output of CMD.EXE to a Pipe

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 […]

Written By
CodeGuru Staff
CodeGuru Staff
Apr 4, 1999
1 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

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.

BOOL CShellView::CreateShellRedirect()
{
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) )
{
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;
}
// Create noninheritable read handle and close the inheritable read handle.
fSuccess = DuplicateHandle( GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup ,
0, FALSE,
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
TRACE0( _T(“DuplicateHandle failed\n”) );
return FALSE;
}
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) )
{
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);
// Now create the child process.
if( !CreateChildProcess(dwProcessId) )
{
TRACE0( _T(“CreateChildProcess failed\n”) );
return FALSE;
}
// After process creation, restore the saved STDIN and STDOUT.
if( !SetStdHandle(STD_INPUT_HANDLE, hSaveStdin) )
{
TRACE0( _T(“Re-redirecting Stdin failed\n”) );
return FALSE;
}
if( !SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout) )
{
TRACE0( _T(“Re-redirecting Stdout failed\n”) );
return FALSE;
}
m_pReadThread =
fxBeginThread( (AFX_THREADPROC)ReadPipeThreadProc,(LPVOID)this );
if( !m_pReadThread )
{
TRACE0( _T(“Cannot start read-redirect thread!\n”) );
return FALSE;
}
return TRUE;
}
BOOL CShellView::CreateChildProcess(DWORD& dwProcessId)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
// 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

CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.