|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionTo redirect the input/output of a console application is interesting and useful. You can display the child's output in a window (just like Visual Studio's output window), or search some keywords in the output string to determine if the child process has completed its work successfully. An old, 'ugly' DOS program could become an useful component of your fancy Win32 GUI program. My idea is to develop a simple, easy to use redirector class which can redirect an arbitrary console, and won't be affected by the behavior of the child process. BackgroundThe technique of redirecting the input/output of a console process is very sample: The However, MSDN's sample code has two big problem. First, it assumes the child process will send output at first, then wait for input, then flush the output buffer and exit. If the child process doesn't behave like that, the parent process will be hung up. The reason of this is the Second, It has problem to redirect a 16-bit console (including console based MS-DOS applications.) On Windows 9x, ReadFile remains blocked even after the child process has terminated; On Windows NT/XP, Solving the block problem of ReadFileTo prevent the parent process from being blocked by By calling The class for (;;) { // redirect stdout till there's no more data. nRet = pRedir->RedirectStdout(); if (nRet <= 0) break; // check if the child process has terminated. DWORD dwRc = ::WaitForMultipleObjects( 2, aHandles, FALSE, pRedir->m_dwWaitTime); if (WAIT_OBJECT_0 == dwRc) // the child process ended { ... break; } if (WAIT_OBJECT_0+1 == dwRc) // m_hEvtStop was signalled, exit { ... break; } } This is the main loop of the for (;;) { DWORD dwAvail = 0; if (!::PeekNamedPipe(m_hStdoutRead, NULL, 0, NULL, &dwAvail, NULL)) // error, the child process might ended break; if (!dwAvail) // no data available, return return 1; char szOutput[256]; DWORD dwRead = 0; if (!::ReadFile(m_hStdoutRead, szOutput, min(255, dwAvail), &dwRead, NULL) || !dwRead) // error, the child process might ended break; szOutput[dwRead] = 0; WriteStdOut(szOutput); // display the output }
int nSize = m_pWnd->GetWindowTextLength(); // m_pWnd points to a multiline Edit control m_pWnd->SetSel(nSize, nSize); m_pWnd->ReplaceSel(pszOutput); // add the message to the end of Edit control To redirect DOS console based applications on NT/2000/XPMSDN's solution is to launch an intermediate Win32 Console application as a stub process between the Win32 parent and the 16-bit console based child. In fact the DOS prompt program (on NT/XP it's cmd.exe, on 9x it's command.com) is a natural stub process we just need. We can test this in RedirDemo.exe:
Apparently this is not a good solution because it's too complicated. A more effective way is to use a batch file as the stub. Edit stub.bat file like this: %1 %2 %3 %4 %5 %6 %7 %8 %9
Then run a command like 'stub.bat dosapp.exe', then the 16-bit DOS console application runs OK.
|
||||||||||||||||||||||