AllocConsole() not displaying cout
I vaguely recall that you might need to redirect the stdout to the console. I might be wrong though (since you had your code working earlier):
AllocConsole();
freopen("CONOUT$", "w", stdout);
std::cout << "This works" << std::endl;
Unable to write to AllocConsole()
After allocating a new console via AllocConsole()
, you need to re-open the standard streams (stdout
, stderr
, stdin
) before you can use them.
You can do so by using freopen
(in newer versions of Visual Studio you need to use freopen_s
)
Example:
FILE *fDummy;
freopen_s(&fDummy, "CONIN$", "r", stdin);
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONOUT$", "w", stdout);
If you want to use the deprecated freopen
you can disable the warning by #define
ing _CRT_SECURE_NO_WARNINGS
.
If you also want to use the wide-character streams (std::wcout
, std::wcerr
, etc...), you need to call SetStdHandle()
to set a new output handle for your process. You can get the required file handle for this by calling CreateFile()
with CONOUT$
/ CONIN$
as file name:
HANDLE hConOut = CreateFile(_T("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
Additionally, if you tried to use one of the streams before re-opening them, they will have the std::ios_base::badbit
and std::ios_base::failbit
set in their iostate
, so subsequent writes / reads will be ignored.
You can reset the stream state with .clear()
, after which you can read/write from/to the stream again:
std::cout.clear();
std::cin.clear();
Heres a full example of re-opening all the streams after AllocConsole()
:
void CreateConsole()
{
if (!AllocConsole()) {
// Add some error handling here.
// You can call GetLastError() to get more info about the error.
return;
}
// std::cout, std::clog, std::cerr, std::cin
FILE* fDummy;
freopen_s(&fDummy, "CONOUT$", "w", stdout);
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONIN$", "r", stdin);
std::cout.clear();
std::clog.clear();
std::cerr.clear();
std::cin.clear();
// std::wcout, std::wclog, std::wcerr, std::wcin
HANDLE hConOut = CreateFile(_T("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE hConIn = CreateFile(_T("CONIN$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
SetStdHandle(STD_ERROR_HANDLE, hConOut);
SetStdHandle(STD_INPUT_HANDLE, hConIn);
std::wcout.clear();
std::wclog.clear();
std::wcerr.clear();
std::wcin.clear();
}
AllocConsole not printing when in Visual Studio
I got the same issue. Turns out writing to the console works in visual studio only when debugging in hosted process. Go to Project Properties -> Debug -> Enable Debuggers and make sure 'Enable Visual Studio hosting process' is checked.
Doing a std::endl before AllocConsole causes no display of std::cout
Before you call RedirectIOToConsole()
there is nothing for cout
to output onto. Since cout
is buffered, the output is stored in a buffer until a flush
is performed. endl
contains a flush
.
When you try to flush the output with no console available, the cout
stream sets the badbit
in the iostate
.
When you then do the next step of cout << "My Trace 2" << endl;
the output is not proceeding because before actually writing the data to the output file (stdout), cout
checks the iostate
and says "Oh, this is not good, we have badbit
set" and bails out without trying to write.
You could, in theory, fix this by calling cout.clear();
, but I would suggest that it's a better plan to not call cout
before you have allocated a console - it serves no purpose to output things before you have something to output to.
Console showing when running winapi program
When you link a Windows executable, you have the option of determining a flag in the PE header that determines whether or not the executable represents a console application or a Windows application. The only thing this flag does is determine whether Windows creates a console for your program when you start it (and possibly also connect the standard handles to it; I don't know for sure, but the AllocConsole()
docs imply so). Typical Windows programs don't use a console, so this is a good thing for them.
I don't know what project templates Code::Blocks provides by default, but Visual Studio provides both console application and Windows application templates, and which one you choose determines what this linker flag is set to. You should be able to change the flag with either IDE in its project preferences page. (The different project templates mainly give you different starting code and settings to work from, but they're by no means absolute measures of what you can write.)
If you used Code::Blocks without making a project (somehow; I don't use Code::Blocks) it's important to know that MinGW, which is likely to be the compiler that Code::Blocks comes with, produces console applications by default.
As Jonathan Potter's comment above explained, there's nothing special about the console; you can create consoles and use them on the fly in your program. See MSDN for details. If you do this, however, see Remy Lebeau's comment below as you need to tell stdio (and iostream, in the case of C++) about it. Likewise, a console program is free to create regular windows as it so chooses.
The last pitfall is that Microsoft's compiler actually distinguishes between main)
for console applications and WinMain()
for Windows applications. WinMain()
was introduced because 16-bit Windows needed extra information at startup: the hPrevInstance
and lpCmdLine
arguments are deprecated, and the hInstance
and nCmdShow
arguments can be accessed through a variety of other means. That being said, I don't know how to get Microsoft's compilers to accept main()
on a Windows application project and vice versa; you could probably get somewhere with some searching...
Also be careful when you refer to the components of Visual Studio: Visual C++ and Visual Basic are very different things.
Console.Out Output is showing in Output Window, Needed in AllocConsole()
AllocConsole()
does not work on it's own, because VS 2017 does some "debug stdout redirect magic". To fix this you need to create a console with AllocConsole()
and fix the stdout handle.
Here is the snipped I found:
[DllImport("kernel32.dll",
EntryPoint = "AllocConsole",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int AllocConsole();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
uint lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
uint hTemplateFile);
private const int MY_CODE_PAGE = 437;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_WRITE = 0x2;
private const uint OPEN_EXISTING = 0x3;
public static void CreateConsole()
{
AllocConsole();
IntPtr stdHandle = CreateFile(
"CONOUT$",
GENERIC_WRITE,
FILE_SHARE_WRITE,
0, OPEN_EXISTING, 0, 0
);
SafeFileHandle safeFileHandle = new SafeFileHandle(stdHandle, true);
FileStream fileStream = new FileStream(safeFileHandle, FileAccess.Write);
Encoding encoding = System.Text.Encoding.GetEncoding(MY_CODE_PAGE);
StreamWriter standardOutput = new StreamWriter(fileStream, encoding);
standardOutput.AutoFlush = true;
Console.SetOut(standardOutput);
Console.Write("This will show up in the Console window.");
}
Special thanks to Ramkumar Ramesh for the work-around:
Console Output is gone in VS2017
No console output when using AllocConsole and target architecture x86
When "Enable native code debugging" is enabled, output from consoles crated with AllocConsole
is redirected to the debug output window instead.
The reason this only happens in x86 and not AnyCPU is because you can only debug native code in an x86 application.
Note that this behavior only occurs with consoles created with AllocConsole
. A console application's output is not redirected.
EDIT: The other reason for the console not outputting text is when you've written to the console before calling AllocConsole
.
Regardless of the reason, this code will restore output if it was redirected, and reopen the console in case it's invalid. It uses the magic number 7 which is what the handle of stdout
usually equals to.
using System;
using System.IO;
using System.Runtime.InteropServices;
public static class ConsoleHelper
{
public static void CreateConsole()
{
AllocConsole();
// stdout's handle seems to always be equal to 7
IntPtr defaultStdout = new IntPtr(7);
IntPtr currentStdout = GetStdHandle(StdOutputHandle);
if (currentStdout != defaultStdout)
// reset stdout
SetStdHandle(StdOutputHandle, defaultStdout);
// reopen stdout
TextWriter writer = new StreamWriter(Console.OpenStandardOutput())
{ AutoFlush = true };
Console.SetOut(writer);
}
// P/Invoke required:
private const UInt32 StdOutputHandle = 0xFFFFFFF5;
[DllImport("kernel32.dll")]
private static extern IntPtr GetStdHandle(UInt32 nStdHandle);
[DllImport("kernel32.dll")]
private static extern void SetStdHandle(UInt32 nStdHandle, IntPtr handle);
[DllImport("kernel32")]
static extern bool AllocConsole();
}
See How to detect if Console.In (stdin) has been redirected? for another way to detect if the console handles have been redirected.
PostMessage Not working with allocated console in winform app
Try sending a WM_SYSCOMMAND
message with wParam
= SC_CLOSE
. This more closely mimics selecting 'Close' from the system menu.
Related Topics
C++11 Constexpr Function Pass Parameter
How to Immediately Invoke a C++ Lambda
Trial-Division Code Runs 2X Faster as 32-Bit on Windows Than 64-Bit on Linux
Initializer-List-Constructing a Vector of Noncopyable (But Movable) Objects
Implicit Conversion from Char** to Const Char**
How to Implement a Natural Sort Algorithm in C++
2D-Array as Argument to Function
How to Use Glortho() in Opengl
Pthreads: Thread Starvation Caused by Quick Re-Locking
What Is/Are the Purpose(S) of Inline
Qml and C++ Image Interoperability
How to Return in Void Function
Calling Initializer_List Constructor via Make_Unique/Make_Shared
How to Build Cmake Externalproject While Configurating Main One
What Happens When You Call Data() on a Std::Vector<Bool>