If I have a native C++ windows program (i.e. the entry point is WinMain) how do I view output from console functions like std::cout?
If I have a native C++ windows program (i.e. the entry point is WinMain) how do I view output from console functions like std::cout?
Check out Adding Console I/O to a Win32 GUI App. This may help you do what you want.
If you don't have, or can't modify the code, try the suggestions found here to redirect console output to a file.
Edit: bit of thread necromancy here. I first answered this 9ish years ago, in the early days of SO, before the (good) policy of non-link-only answers came into effect. I'll repost the code from the original article in the hope to atone for my past sins.
guicon.cpp -- A console redirection function
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <fstream>
#ifndef _USE_OLD_IOSTREAMS
using namespace std;
#endif
// maximum mumber of lines the output console should have
static const WORD MAX_CONSOLE_LINES = 500;
#ifdef _DEBUG
void RedirectIOToConsole()
{
int hConHandle;
long lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
// allocate a console for this app
AllocConsole();
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
coninfo.dwSize.Y = MAX_CONSOLE_LINES;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
// redirect unbuffered STDOUT to the console
lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 );
// redirect unbuffered STDIN to the console
lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "r" );
*stdin = *fp;
setvbuf( stdin, NULL, _IONBF, 0 );
// redirect unbuffered STDERR to the console
lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stderr = *fp;
setvbuf( stderr, NULL, _IONBF, 0 );
// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
// point to console as well
ios::sync_with_stdio();
}
#endif
//End of File
guicon.h -- Interface to console redirection function
#ifndef __GUICON_H__
#define __GUICON_H__
#ifdef _DEBUG
void RedirectIOToConsole();
#endif
#endif
// End of File
test.cpp -- Demonstrating console redirection
#include <windows.h>
#include <iostream>
#include <fstream>
#include <conio.h>
#include <stdio.h>
#ifndef _USE_OLD_OSTREAMS
using namespace std;
#endif
#include "guicon.h"
#include <crtdbg.h>
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
#ifdef _DEBUG
RedirectIOToConsole();
#endif
int iVar;
// test stdio
fprintf(stdout, "Test output to stdout\n");
fprintf(stderr, "Test output to stderr\n");
fprintf(stdout, "Enter an integer to test stdin: ");
scanf("%d", &iVar);
printf("You entered %d\n", iVar);
//test iostreams
cout << "Test output to cout" << endl;
cerr << "Test output to cerr" << endl;
clog << "Test output to clog" << endl;
cout << "Enter an integer to test cin: ";
cin >> iVar;
cout << "You entered " << iVar << endl;
#ifndef _USE_OLD_IOSTREAMS
// test wide iostreams
wcout << L"Test output to wcout" << endl;
wcerr << L"Test output to wcerr" << endl;
wclog << L"Test output to wclog" << endl;
wcout << L"Enter an integer to test wcin: ";
wcin >> iVar;
wcout << L"You entered " << iVar << endl;
#endif
// test CrtDbg output
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR);
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR);
_RPT0(_CRT_WARN, "This is testing _CRT_WARN output\n");
_RPT0(_CRT_ERROR, "This is testing _CRT_ERROR output\n");
_ASSERT( 0 && "testing _ASSERT" );
_ASSERTE( 0 && "testing _ASSERTE" );
Sleep(2000);
return 0;
}
//End of File
The problem some of the other answers is that they unnecessarily create new FILE instances which are then leaked and can cause debug assertions in the CRT cleanup code.
freopen_s is all that is really needed:
FILE* fp = nullptr;
freopen_s(&fp, "CONIN$", "r", stdin);
freopen_s(&fp, "CONOUT$", "w", stdout);
freopen_s(&fp, "CONOUT$", "w", stderr);
You'll probably want to do a little error checking and cleanup as well. Below is the complete solution that I currently use.
Redirecting Console Standard IO:
bool RedirectConsoleIO()
{
bool result = true;
FILE* fp;
// Redirect STDIN if the console has an input handle
if (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE)
if (freopen_s(&fp, "CONIN$", "r", stdin) != 0)
result = false;
else
setvbuf(stdin, NULL, _IONBF, 0);
// Redirect STDOUT if the console has an output handle
if (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE)
if (freopen_s(&fp, "CONOUT$", "w", stdout) != 0)
result = false;
else
setvbuf(stdout, NULL, _IONBF, 0);
// Redirect STDERR if the console has an error handle
if (GetStdHandle(STD_ERROR_HANDLE) != INVALID_HANDLE_VALUE)
if (freopen_s(&fp, "CONOUT$", "w", stderr) != 0)
result = false;
else
setvbuf(stderr, NULL, _IONBF, 0);
// Make C++ standard streams point to console as well.
ios::sync_with_stdio(true);
// Clear the error state for each of the C++ standard streams.
std::wcout.clear();
std::cout.clear();
std::wcerr.clear();
std::cerr.clear();
std::wcin.clear();
std::cin.clear();
return result;
}
Releasing a Console:
bool ReleaseConsole()
{
bool result = true;
FILE* fp;
// Just to be safe, redirect standard IO to NUL before releasing.
// Redirect STDIN to NUL
if (freopen_s(&fp, "NUL:", "r", stdin) != 0)
result = false;
else
setvbuf(stdin, NULL, _IONBF, 0);
// Redirect STDOUT to NUL
if (freopen_s(&fp, "NUL:", "w", stdout) != 0)
result = false;
else
setvbuf(stdout, NULL, _IONBF, 0);
// Redirect STDERR to NUL
if (freopen_s(&fp, "NUL:", "w", stderr) != 0)
result = false;
else
setvbuf(stderr, NULL, _IONBF, 0);
// Detach from console
if (!FreeConsole())
result = false;
return result;
}
Resizing Console Buffer:
void AdjustConsoleBuffer(int16_t minLength)
{
// Set the screen buffer to be big enough to scroll some text
CONSOLE_SCREEN_BUFFER_INFO conInfo;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &conInfo);
if (conInfo.dwSize.Y < minLength)
conInfo.dwSize.Y = minLength;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), conInfo.dwSize);
}
Allocating a New Console:
bool CreateNewConsole(int16_t minLength)
{
bool result = false;
// Release any current console and redirect IO to NUL
ReleaseConsole();
// Attempt to create new console
if (AllocConsole())
{
AdjustConsoleBuffer(minLength);
result = RedirectConsoleIO();
}
return result;
}
Attaching to Parent's Console:
bool AttachParentConsole(int16_t minLength)
{
bool result = false;
// Release any current console and redirect IO to NUL
ReleaseConsole();
// Attempt to attach to parent process's console
if (AttachConsole(ATTACH_PARENT_PROCESS))
{
AdjustConsoleBuffer(minLength);
result = RedirectConsoleIO();
}
return result;
}
Calling from WinMain:
Link with /SUBSYSTEM:Windows
int APIENTRY WinMain(
HINSTANCE /*hInstance*/,
HINSTANCE /*hPrevInstance*/,
LPTSTR /*lpCmdLine*/,
int /*cmdShow*/)
{
if (CreateNewConsole(1024))
{
int i;
// test stdio
fprintf(stdout, "Test output to stdout\n");
fprintf(stderr, "Test output to stderr\n");
fprintf(stdout, "Enter an integer to test stdin: ");
scanf("%d", &i);
printf("You entered %d\n", i);
// test iostreams
std::cout << "Test output to std::cout" << std::endl;
std::cerr << "Test output to std::cerr" << std::endl;
std::clog << "Test output to std::clog" << std::endl;
std::cout << "Enter an integer to test std::cin: ";
std::cin >> i;
std::cout << "You entered " << i << std::endl;
std::cout << endl << "Press any key to continue..." << endl;
_getch();
ReleaseConsole();
}
return 0;
};
You can also reopen the cout and cerr streams to output to a file as well. The following should work for this:
#include <iostream>
#include <fstream>
int main ()
{
std::ofstream file;
file.open ("cout.txt");
std::streambuf* sbuf = std::cout.rdbuf();
std::cout.rdbuf(file.rdbuf());
//cout is now pointing to a file
return 0;
}
Actually there is a much simpler solution than any proposed so far. Your Windows program will have a WinMain function so just add this "dummy" main function as well
int main()
{
return WinMain(GetModuleHandle(NULL), NULL, GetCommandLineA(), SW_SHOWNORMAL);
}
You can now compile using MSVC like this
cl /nologo /c /EHsc myprog.c
link /nologo /out:myprog.exe /subsystem:console myprog.obj user32.lib gdi32.lib
(you may need to add more library links)
When you run the program any printf will be written to the command prompt.
If you are using gcc (mingw) to compile for Windows you don't need a dummy main function, just do
gcc -o myprog.exe myprog.c -luser32 -lgdi32
(ie avoid using the -mwindows flag which will prevent writing to a console. That flag will be useful when you create the final GUI release) Again you may need to specify more libraries if using more windows features)
creating a pipe, execute the program console CreateProcess() and read with ReadFile() or writes in console WriteFile()
HANDLE hRead ; // ConsoleStdInput
HANDLE hWrite; // ConsoleStdOutput and ConsoleStdError
STARTUPINFO stiConsole;
SECURITY_ATTRIBUTES segConsole;
PROCESS_INFORMATION priConsole;
segConsole.nLength = sizeof(segConsole);
segConsole.lpSecurityDescriptor = NULL;
segConsole.bInheritHandle = TRUE;
if(CreatePipe(&hRead,&hWrite,&segConsole,0) )
{
FillMemory(&stiConsole,sizeof(stiConsole),0);
stiConsole.cb = sizeof(stiConsole);
GetStartupInfo(&stiConsole);
stiConsole.hStdOutput = hWrite;
stiConsole.hStdError = hWrite;
stiConsole.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
stiConsole.wShowWindow = SW_HIDE; // execute hide
if(CreateProcess(NULL, "c:\\teste.exe",NULL,NULL,TRUE,NULL,
NULL,NULL,&stiConsole,&priConsole) == TRUE)
{
//readfile and/or writefile
}
}
Don't quote me on this, but the Win32 console API might be what you're looking for. If you're just doing this for debugging purposes, however, you might be more interested in running DebugView and calling the DbgPrint function.
This of course assumes its your application you want sending console output, not reading it from another application. In that case, pipes might be your friend.
As mentioned there and there the easiest solution is to use your Project Property Pages to switch back and forth between CONSOLE and WINDOWS SubSytems to enable or disable console output at will.
Your program will just need main and WinMain entry points to make sure both configuration are compiling.
The main function simply calling WinMain as shown below for instance:
int main()
{
cout << "Output standard\n";
cerr << "Output error\n";
return WinMain(GetModuleHandle(NULL), NULL, GetCommandLineA(), SW_SHOWNORMAL);
}
Since there's no console window, this is impossible difficult. (Learn something new every day - I never knew about the console functions!)
Is it possible for you to replace your output calls? I will often use TRACE or OutputDebugString to send information to the Visual Studio output window.