6

Where does fprintf(stdout/stderr) print to in Visual Studio when compiling Win32 app? I keep hearing it goes to the output but I can't see it!.

Whats the standard way of printing to the output log without having a console window in c++?

Josh Elias
  • 3,250
  • 7
  • 42
  • 73

1 Answers1

15

If your program is linked with /SUBSYSTEM:WINDOWS you will not see the console output unless you allocate a console.

Here is code for the allocate console option. With this method you should not need to change your linker settings or create a WinMain.

static void OpenConsole()
{
    int outHandle, errHandle, inHandle;
    FILE *outFile, *errFile, *inFile;
    AllocConsole();
    CONSOLE_SCREEN_BUFFER_INFO coninfo;
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
    coninfo.dwSize.Y = 9999;
    SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);

    outHandle = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
    errHandle = _open_osfhandle((long)GetStdHandle(STD_ERROR_HANDLE),_O_TEXT);
    inHandle = _open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE),_O_TEXT );

    outFile = _fdopen(outHandle, "w" );
    errFile = _fdopen(errHandle, "w");
    inFile =  _fdopen(inHandle, "r");

    *stdout = *outFile;
    *stderr = *errFile;
    *stdin = *inFile;

    setvbuf( stdout, NULL, _IONBF, 0 );
    setvbuf( stderr, NULL, _IONBF, 0 );
    setvbuf( stdin, NULL, _IONBF, 0 );

    std::ios::sync_with_stdio();

}

If you do not want to allocate a console directly you can also change the subsystem from /SUBSYSTEM:WINDOWS to /SUBSYSTEM:CONSOLE via changing the Subsystem of the linker settings. Remember when /SUBSYSTEM:CONSOLE is enabled the gui will still work the same as before but windows will create a console window for you along with your application.

In my Qt code that is all that is needed. However when I tried MFC in VisualStudio and set the subsystem to console via the linker setting. I got the following error:

1>------ Build started: Project: MFCApplication1, Configuration: Debug Win32 ------
1>  MFCApplication1.cpp
1>msvcrtd.lib(crtexe.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
1>X:\Test\VC.110\MFCTest\MFCApplication1\Debug\MFCApplication1.exe : fatal error LNK1120: 1 unresolved externals

This is caused by the entry point defaulting to main() in console applications and WinMain in windows applications. To fix this I had to add the following to the Entry Point setting of the Advanced Linker settings: "wWinMainCRTStartup"

In the comments Ben Voigt suggested an alternate method. Using editbin to change the subsystem does not require a change in the entry point. This is indeed the case. I put removed the entry point and put windows back as the subsystem built the test application then used editbin to change the subsystem using the following command:

X:\Test\VC.110\MFCTest\MFCApplication1\Debug>editbin MFCApplication1.exe /SUBSYSTEM:CONSOLE
Microsoft (R) COFF/PE Editor Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

And I got the output I expected in the console:

X:\Test\VC.110\MFCTest\MFCApplication1\Debug>MFCApplication1.exe
Hello from a windows application!
 

Note: With the editbin method you need to renable this every time you update the executable.

And finally on either method once you have the console printf or std::cout will work. For example in my test MFC application I added the following line to the constructor of the CMFCApplication1App class:

std::cout << "Hello from a windows application!" << std::endl;
drescherjm
  • 10,365
  • 5
  • 44
  • 64
  • This is in the subsystem tab of the linker settings. This works for me in Qt however I am having a problem doing this for MFC under VS2012 because of the entry point changes if you use the console subsystem. Are you using MFC? – drescherjm Dec 12 '12 at 18:18
  • 3
    You can also use `editbin` to change the subsystem -- this won't affect the linking process so it won't change the entrypoint lookup logic. – Ben Voigt Dec 12 '12 at 18:31
  • Note that changing subsystem works, even if the project target is a DLL used by another console-application. – leiflundgren Feb 20 '13 at 14:22
  • I tried that chunk of code to allocate a console. Nothing shows up in that window. What would keep it from working? – DarenW Dec 21 '16 at 23:44
  • Not sure. I will see if I can duplicate the issue tomorrow. – drescherjm Dec 21 '16 at 23:46
  • I found a related trick, which works for us, on the Matlab Answers site. http://www.mathworks.com/matlabcentral/answers/95351-how-can-i-display-dos-console-outputs-in-the-visual-studio-environment-for-debugging-purposes#answer_104703 – DarenW Dec 22 '16 at 01:31
  • Would be nice to use that OpenConsole() code, though. – DarenW Dec 22 '16 at 01:31