?
Solved

Calling console applications from C++ Builder

Posted on 1999-12-02
2
Medium Priority
?
979 Views
Last Modified: 2012-08-13
I have a set of utilities which are 32 bit console applications which take command line arguments and return output to the console.

How can I incorporate these programs into a C++ Builder program so that I can create a front-end GUI. Note that I don't have the source code for the console apps. (third party software). I need to

a) pass arguments to the apps as command line arguments
b) recover the output of the applications
c) I don't want spurious DOS windows appearing while the apps run.
0
Comment
Question by:hpicd
2 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 200 total points
ID: 2250078
Use

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, dwRetCode;
   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 )
      {
         /* get exit code */
         GetExitCodeProcess ( pi.hProcess, &dwRetCode);
         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
}

This example sends the output to a list box, but I'm sure you'll be able to adapt it for your needs...

Feel free to ask if you encounter problems!
0
 

Author Comment

by:hpicd
ID: 2250154
That looks pretty good and so quick I hardly had time to get a cup of coffee! I will try it this evening and report back if there are any problems.
0

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Article by: evilrix
Looking for a way to avoid searching through large data sets for data that doesn't exist? A Bloom Filter might be what you need. This data structure is a probabilistic filter that allows you to avoid unnecessary searches when you know the data defin…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

601 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question