Redirecting Console Application Stdin/out

I would like to be able to spawn from a Windows application a console application (such as ftp) and redirect the standard input and output.  In particular, I would like to be able to take the standard output/error and send it to a text box on the screen instead of appearing in a DOS window.  Microsoft's developer studio does this when it compiles code.  How do I do this?  I believe it has something to do with CreateProcess and the handles you can specify in the STARTUPINFO structure, but I don't know which handles to specify or how to link them to a text box in my windows application.
ardolinoAsked:
Who is Participating?
 
jkrConnect With a Mentor Commented:
Try the following code:

DWORD StartCommandLine( HWND hDlg )
{
   OSVERSIONINFO osvi;
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
   HANDLE hInputRead, hInputWrite;
   HANDLE hOutputRead, hOutputWrite;
   HANDLE hDupInputWrite;
   HANDLE hDupOutputRead;
   BOOL bStatus;
   DWORD dwRead, dwAvail, dwMsg;
   char szInput[ 1024 ];

 
   memset( &si, 0, sizeof(STARTUPINFO) );             //  Initialize structures
   memset( &pi, 0, sizeof(PROCESS_INFORMATION) );
                                        //  Create pipe for console -> GUI data
   bStatus = CreatePipe( &hInputRead, &hInputWrite, NULL, 1024 );
   if( ! bStatus )
      return( FALSE );
                                        //  Create pipe for GUI -> console data
   bStatus = CreatePipe( &hOutputRead, &hOutputWrite, NULL, 1024 );
   if( ! bStatus )
   {
      CloseHandle( hInputRead );           //  Close first pipe if second fails
      CloseHandle( hInputWrite );
      return( FALSE );
   }
                                   //  Make an inheritable pipe endpoint handle
   DuplicateHandle( GetCurrentProcess(), hInputWrite,
                    GetCurrentProcess(), &hDupInputWrite, 0L, TRUE,
                    DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS );
                                            //  and a second for GUI -> console
   DuplicateHandle( GetCurrentProcess(), hOutputRead,
                    GetCurrentProcess(), &hDupOutputRead, 0L, TRUE,
                    DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS );

   si.cb = sizeof(STARTUPINFO);
   si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
   si.wShowWindow = SW_HIDE;        //  Don't show the console window (DOS box)
   si.hStdOutput = hDupInputWrite;             //  Redirect command line to GUI
   si.hStdError = hDupInputWrite;
   si.hStdInput = hDupOutputRead;  //  and send stuff from here to command line

   hPipeOut = hOutputWrite;                  //  Global so window can access it

   memset( &osvi, 0, sizeof(OSVERSIONINFO) );     //  Initialize version struct
   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);           //  Fill in size
   GetVersionEx( &osvi );                               //  Get OS version info
                                                            //  Start a DOS box
   if( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT )           //  If it's WinNT
      bStatus = CreateProcess( NULL, "cmd /K", NULL, NULL, TRUE,
                               0, NULL, NULL, &si, &pi );       //  Use CMD.EXE
   else                                           //  Use command.com for Win95
      bStatus = CreateProcess( NULL, "c:\\command.com", NULL, NULL, TRUE,
                               0, NULL, NULL, &si, &pi );

   CloseHandle( hDupInputWrite );               //  Close duplicates so GUI end
   CloseHandle( hDupOutputRead );                         //  can use the pipes

   if( ! bStatus )
   {
      CloseHandle( hInputRead );
      CloseHandle( hInputWrite );
      CloseHandle( hOutputRead );
      CloseHandle( hOutputWrite );
      return( FALSE );
   }
                     //  Loop until either the window closure sets the event or
   while( WaitForSingleObject( hThreadEvent, 0 ) != WAIT_OBJECT_0 )
   {                                                  //  The dos box is closed
      if( WaitForSingleObject( pi.hProcess, 0 ) == WAIT_OBJECT_0 )
      {
         pi.hProcess = NULL;
         break;
      }

                                                //  If there's anything to read
      if( PeekNamedPipe( hInputRead, szInput, 1024, &dwRead,
                         &dwAvail, &dwMsg ) )
      {                                               //  Read it into a buffer
         ReadFile( hInputRead, szInput, dwAvail, &dwRead, NULL );
         if( dwRead )                        //  and send to the window control
            SendDlgItemMessage( hDlg, 100, LB_ADDSTRING, 0, (LPARAM)szInput );
      }
      Sleep( 100 );                        //  Sit a spell...kick yer shoes off
   }

   if( pi.hProcess )                     //  If the dos box is running, kill it
      TerminateProcess( pi.hProcess, 0 );

   CloseHandle( hInputWrite );
   CloseHandle( hOutputRead );
   return( TRUE );                                      //  And exit the thread
}
0
 
chensuCommented:
HOWTO: Spawn Console Processes with Redirected Standard Handles
http://support.microsoft.com/support/kb/articles/q190/3/51.asp

INFO: Redirection Issues on Windows 95 MS-DOS Applications
http://support.microsoft.com/support/kb/articles/Q150/9/56.ASP
0
 
ardolinoAuthor Commented:
These articles are helpful, but only answer half of my question.  I need to know how to take the information that is coming in/going out from the child's process standard handles and send it to/from a text box in a windows application.
0
 
ardolinoAuthor Commented:
This really isn't what I wanted, but it was sort of helpful.
0
 
dbusherCommented:
I cut an pasted this code into my :
void CDialitDlg::OnDialButton()
function and did a build all (VC++ v4)
and got this error:

error C2599: 'StartCommandLine' : local functions are not supported

I am sure it is a basic error - I am a
new programmer.  Any help in fixing this?
0
All Courses

From novice to tech pro — start learning today.