Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Studio 2012 C++ Standard Output

Tags:

c++

output

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++?

like image 983
Josh Elias Avatar asked Dec 12 '12 13:12

Josh Elias


1 Answers

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;
like image 81
drescherjm Avatar answered Oct 21 '22 06:10

drescherjm