INFO: Calling CRT Output Routines from a GUI Application

This article was previously published under Q105305
To use C Run-time output routines, such as printf(), from a GUIapplication, it is necessary to create a console. The Win32 applicationprogramming interface (API) AllocConsole() creates the console. The CRTroutine setvbuf() removes buffering so that output is visible immediately.

This method works if the GUI application is run from the command line orfrom File Manager. However, this method does not work if the application isstarted from the Program Manager or via the "start" command. The followingcode shows how to work around this problem:
   int hCrt;   FILE *hf;   AllocConsole();   hCrt = _open_osfhandle(             (long) GetStdHandle(STD_OUTPUT_HANDLE),             _O_TEXT          );   hf = _fdopen( hCrt, "w" );   *stdout = *hf;   i = setvbuf( stdout, NULL, _IONBF, 0 );				
This code opens up a new low-level CRT handle to the correct console outputhandle, associates a new stream with that low-level handle, and replacesstdout with that new stream. This process takes care of functions that usestdout, such as printf(), puts(), and so forth. Use the same procedure forstdin and stderr.

Note that this code does not correct problems with handles 0, 1, and 2. Infact, due to other complications, it is not possible to correct this, andtherefore it is necessary to use stream I/O instead of low-level I/O.
When a GUI application is started with the "start" command, the threestandard OS handles STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, andSTD_ERROR_HANDLE are all "zeroed out" by the console initializationroutines. These three handles are replaced by valid values when the GUIapplication calls AllocConsole(). Therefore, once this is done, callingGetStdHandle() will always return valid handle values. The problem is thatthe CRT has already completed initialization before your application gets achance to call AllocConsole(); the three low I/O handles 0, 1, and 2 havealready been set up to use the original zeroed out OS handles, so all CRTI/O is sent to invalid OS handles and CRT output does not appear in theconsole. Use the workaround described above to eliminate this problem.

In the case of starting the GUI application from the command line withoutthe "start" command, the standard OS handles are NOT correctly zeroed out,but are incorrectly inherited from CMD.EXE. When the application's CRTinitializes, the three low I/O handles 0, 1, and 2 are initialized to usethe three handle numbers that the application inherits from CMD.EXE. Whenthe application calls AllocConsole(), the console initialization routinesattempt to replace what the console initialization believes to be invalidstandard OS handle values with valid handle values from the new console. Bycoincidence, because the console initialization routines tend to give outthe same three values for the standard OS handles, the consoleinitilization will replace the standard OS handle values with the samevalues that were there before--the ones inherited from CMD.EXE. Therefore,CRT I/O works in this case.

It is important to realize that the ability to use CRT routines from a GUIapplication run from the command line was not by design so this may notwork in future versions of Windows NT or Windows. In a future version, youmay need the workaround not just for applications started on the commandline with "start <application name>", but also for applications started onthe command line with "application name".
3.10 3.50 CRT redirect std handles

ID d'article : 105305 - Dernière mise à jour : 11/21/2006 15:41:00 - Révision : 4.2

Microsoft Win32 Application Programming Interface

  • kbinfo kbconsole kbkernbase KB105305