Environment: Visual C++ 6.0 SP2, Windows NT 4.0 SP4
(continued)
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;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if( !CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) )
{
TRACE0( _T("Stdout pipe creation failed\n") );
return FALSE;
}
if( !SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) )
{
TRACE0( _T("Redirecting STDOUT failed\n") );
return FALSE;
}
fSuccess = DuplicateHandle( GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup ,
0, FALSE,
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
TRACE0( _T("DuplicateHandle failed\n") );
return FALSE;
}
CloseHandle( hChildStdoutRd );
hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
if( !CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0) )
{
TRACE0( _T("Stdin pipe creation failed\n") );
return FALSE;
}
if( !SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd) )
{
TRACE0( _T("Redirecting Stdin failed\n") );
return FALSE;
}
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup,
0, FALSE,
DUPLICATE_SAME_ACCESS );
if( !fSuccess )
{
TRACE0( _T("DuplicateHandle failed\n") );
return FALSE;
}
CloseHandle(hChildStdinWr);
if( !CreateChildProcess(dwProcessId) )
{
TRACE0( _T("CreateChildProcess failed\n") );
return FALSE;
}
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;
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
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
BOOL ret = CreateProcess( NULL,
shellCmd,
NULL,
NULL,
TRUE,
DETACHED_PROCESS,
NULL,
NULL,
&siStartInfo,
&piProcInfo);
if( ret )
dwProcessId = piProcInfo.dwProcessId;
return ret;
}
Download source - 5 KB
Date Last Updated: April 4, 1999