INFO: Redirection Issues on Windows 95 MS-DOS ApplicationsLast reviewed: April 10, 1997Article ID: Q150956 |
The information in this article applies to:
SUMMARYDue to implementation differences on the Microsoft Windows 95 and Microsoft Windows NT platforms, you need to follow special steps to allow the same code to redirect the output of MS-DOS applications and batch (.BAT) files on both platforms.
MORE INFORMATIONWhen you redirect the output of an MS-DOS application or a batch file to a Win32 GUI or Console application, the intuitive method is to launch the MS-DOS process as a DETACHED_PROCESS with a redirected standard output handle to an anonymous pipe. The parent then uses the read end of the pipe to read the redirected output of the MS-DOS process. This design works as expected on Windows NT. For an example of this design, please refer to the INHERIT sample that ships with the Microsoft Win32 Software Developer Kit (SDK) under the Q&A directory. On Windows 95, however, this design causes the parent process to hang because the redirection pipe does not close when a redirected MS-DOS application or batch file exits. A simple solution is to launch a hidden Win32 console application as an interface between the parent Win32 application and the MS-DOS child. The Win32 application spawns a "hidden" console application that inherits standard handles that have been redirected to an anonymous pipe. The hidden console application then spawns the MS-DOS application, causing the MS-DOS application to inherit the hidden console. This behavior results in the MS-DOS application indirectly inheriting the redirected standard handles of the Win32 application.
Sample CodeThe code below outlines a technique that works correctly on both Windows NT and Windows 95. To explain how the pipes work, two pipes are created, one for standard output and one for standard input. For the standard output pipe, the write end is given to the child process for its standard output and standard error handles. For the standard input handle, the read end is given to the child process for its standard input handle.
/*-----------------------Win32 application code----------------------------This code redirects standard handles of the Win32 application and then spawns a console application (CONSPAWN.EXE.) with a hidden window. CONSPAWN inherits the redirected standard handles and spawns the application passed to it on its Command line (DOSAPP.EXE.) When DOSAPP.EXE writes to its STDOUT or STDERR handles, the output is redirected to the pipe created in this Win32 application. -------------------------------------------------------------------------*/
SECURITY_ATTRIBUTES sa = {0}; STARTUPINFO si = {0}; PROCESS_INFORMATION pi = {0}; HANDLE hPipeOutputRead = NULL; HANDLE hPipeOutputWrite = NULL; HANDLE hPipeInputRead = NULL; HANDLE hPipeInputWrite = NULL; BOOL bTest = 0; DWORD dwNumberOfBytesRead = 0; CHAR szMsg[100]; CHAR szBuffer[256]; sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; // Create pipe for standard output redirection. CreatePipe(&hPipeOutputRead, // read handle &hPipeOutputWrite, // write handle &sa, // security attributes 0 // number of bytes reserved for pipe - 0 default ); // Create pipe for standard input redirection. CreatePipe(&hPipeInputRead, // read handle &hPipeInputWrite, // write handle &sa, // security attributes 0 // number of bytes reserved for pipe - 0 default ); // Make child process use hPipeOutputWrite as standard out, // and make sure it does not show on screen. si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.wShowWindow = SW_HIDE; si.hStdInput = hPipeInputRead; si.hStdOutput = hPipeOutputWrite; si.hStdError = hPipeOutputWrite; CreateProcess ( NULL, "CONSPAWN.EXE DOSAPP.EXE", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); // Now that handles have been inherited, close it to be safe. // You don't want to read or write to them accidentally. CloseHandle(hPipeOutputWrite); CloseHandle(hPipeInputRead); // Now test to capture DOS application output by reading // hPipeOutputRead. Could also write to DOS application // standard input by writing to hPipeInputWrite. while(TRUE) { bTest=ReadFile( hPipeOutputRead, // handle of the read end of our pipe &szBuffer, // address of buffer that receives data 256, // number of bytes to read &dwNumberOfBytesRead, // address of number of bytes read NULL // non-overlapped. ); if (!bTest){ wsprintf(szMsg, "Error #%d reading pipe.",GetLastError()); MessageBox(NULL, szMsg, "Test", MB_OK); break; } // do something with data. szBuffer[dwNumberOfBytesRead] = 0; // null terminate MessageBox(NULL, szBuffer, "Test", MB_OK); } // Wait for CONSPAWN to finish. WaitForSingleObject (pi.hProcess, INFINITE); // Close all remaining handles CloseHandle (pi.hProcess); CloseHandle (hPipeOutputRead); CloseHandle (hPipeInputWrite); /*----------Console application (CONSPAWN.EXE) code-----------------------This program (CONSPAWN) is launched with a hidden console that inherits the redirected standard handles of the Win32 application. The application that CONSPAWN launches in the same hidden console inherits the same redirected standard handles. This behavior redirects the standard handles of the MS-DOS application to be launched to the pipe created in the parent Win32 application. -------------------------------------------------------------------------*/
#include <windows.h> #include <stdio.h> void main (int argc, char *argv[]) { BOOL bRet = FALSE; STARTUPINFO si = {0}; PROCESS_INFORMATION pi = {0}; // Make child process use this app's standard files. si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = GetStdHandle (STD_INPUT_HANDLE); si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE); si.hStdError = GetStdHandle (STD_ERROR_HANDLE); bRet = CreateProcess (NULL, argv[1], NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi ); if (bRet) { WaitForSingleObject (pi.hProcess, INFINITE); CloseHandle (pi.hProcess); CloseHandle (pi.hThread); } } |
Additional query words: 95 win95 winnt inherit std redirect
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |