INFO: Redirection Issues on Windows 95 MS-DOS Applications

Last reviewed: April 10, 1997
Article ID: Q150956
The information in this article applies to:
  • Microsoft Win32 Application Programming Interface (API) included with: - Microsoft Windows 95

SUMMARY

Due 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 INFORMATION

When 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 Code

The 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
Keywords : BseCon kbprg
Platform : Win95
Issue type : kbinfo


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: April 10, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.