Redirecting Cout to a Console in Windows

Redirecting cout to a console in windows


Updated Feb 2018:

Here is the latest version of a function which fixes this problem:

void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr)
{
// Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been
// observed that the file number of our standard handle file objects can be assigned internally to a value of -2
// when not bound to a valid target, which represents some kind of unknown internal invalid state. In this state our
// call to "_dup2" fails, as it specifically tests to ensure that the target file number isn't equal to this value
// before allowing the operation to continue. We can resolve this issue by first "re-opening" the target files to
// use the "nul" device, which will place them into a valid state, after which we can redirect them to our target
// using the "_dup2" function.
if (bindStdIn)
{
FILE* dummyFile;
freopen_s(&dummyFile, "nul", "r", stdin);
}
if (bindStdOut)
{
FILE* dummyFile;
freopen_s(&dummyFile, "nul", "w", stdout);
}
if (bindStdErr)
{
FILE* dummyFile;
freopen_s(&dummyFile, "nul", "w", stderr);
}

// Redirect unbuffered stdin from the current standard input handle
if (bindStdIn)
{
HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE);
if(stdHandle != INVALID_HANDLE_VALUE)
{
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
if(fileDescriptor != -1)
{
FILE* file = _fdopen(fileDescriptor, "r");
if(file != NULL)
{
int dup2Result = _dup2(_fileno(file), _fileno(stdin));
if (dup2Result == 0)
{
setvbuf(stdin, NULL, _IONBF, 0);
}
}
}
}
}

// Redirect unbuffered stdout to the current standard output handle
if (bindStdOut)
{
HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
if(stdHandle != INVALID_HANDLE_VALUE)
{
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
if(fileDescriptor != -1)
{
FILE* file = _fdopen(fileDescriptor, "w");
if(file != NULL)
{
int dup2Result = _dup2(_fileno(file), _fileno(stdout));
if (dup2Result == 0)
{
setvbuf(stdout, NULL, _IONBF, 0);
}
}
}
}
}

// Redirect unbuffered stderr to the current standard error handle
if (bindStdErr)
{
HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE);
if(stdHandle != INVALID_HANDLE_VALUE)
{
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
if(fileDescriptor != -1)
{
FILE* file = _fdopen(fileDescriptor, "w");
if(file != NULL)
{
int dup2Result = _dup2(_fileno(file), _fileno(stderr));
if (dup2Result == 0)
{
setvbuf(stderr, NULL, _IONBF, 0);
}
}
}
}
}

// Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the
// standard streams before they refer to a valid target will cause the iostream objects to enter an error state. In
// versions of Visual Studio after 2005, this seems to always occur during startup regardless of whether anything
// has been read from or written to the targets or not.
if (bindStdIn)
{
std::wcin.clear();
std::cin.clear();
}
if (bindStdOut)
{
std::wcout.clear();
std::cout.clear();
}
if (bindStdErr)
{
std::wcerr.clear();
std::cerr.clear();
}
}

In order to define this function, you'll need the following set of includes:

#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include <iostream>

In a nutshell, this function synchronizes the C/C++ runtime standard input/output/error handles with the current standard handles associated with the Win32 process. As mentioned in the documentation, AllocConsole changes these process handles for us, so all that's required is to call this function after AllocConsole to update the runtime handles, otherwise we'll be left with the handles that were latched when the runtime was initialized. Basic usage is as follows:

// Allocate a console window for this process
AllocConsole();

// Update the C/C++ runtime standard input, output, and error targets to use the console window
BindCrtHandlesToStdHandles(true, true, true);

This function has gone through several revisions, so check the edits to this answer if you're interested in historical information or alternatives. The current answer is the best solution to this problem however, giving the most flexibility and working on any Visual Studio version.

Windows batch redirect output to console

This is more a workaround.

The idea is to a use a pipe program in order to redirect the output of the Windows program to the console:

SomeWinProg SomeArgs 2>>&1 | SomePipeProg PipeProgArgs

As a pipe program you may use a program that passes throug everything, like:

SomeWinProg SomeArgs 2>>&1 | findstr /r "/c:.*"

If this works or not depends on the Windows program.

Concerning the timing:

There may be some trouble when you have a long time running Windows program which produces sporadic output or when the output is done always to the same line (no line feeds, only carriage returns) and you want to have the output in real time.

In these cacses Windows programs like findstr or find are a little bit weak.

On github there is an implementation of mtee thats fits better:

SomeWinProg SomeArgs 2>>&1 | mtee nul

Redirect stdout to parent process console window

A process can only write directly to the console it is attached to. If a child process is created with its own console, or allocates its own console once started, it can't subsequently write to the parent's console.

If the parent process creates an anonymous pipe it can use the write handle as the child process's stdout. The parent process would need to service the pipe; e.g. it might have a thread to read data from the pipe and write it to its own console.

The child process would not have to worry whether it was writing to a file or the parent process. It would all be normal I/O to stdout.

Redirect stdout and stderr to the output debug console of microsoft visual studio

You can indeed redirect std::out and std::err. Simply right click on your project in the solution explorer and select Properties. Then select Configuration Properties -> Debugging and put the appropriate arguments into the Command Arguments field. For example, to redirect std::err to a file, I would type in 2> ErrorLog.txt.

The things you type in Command Arguments simply get appended as command line arguments when Visual Studio runs your program, just like you had manually typed them in to the console. So, the above example simply tells VisualStudio to run your program with the command <programName>.exe 2> ErrorLog.txt instead of just <programName>.exe.

How can I properly redirect C and C++ I/O to a winapi console handle?

This should work, but I didn't test it:

void RedirectIOConsole()
{
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONERR$", "w", stderr);
}

WinAPI - How to redirect all stdout of a program and external DLLs to the Win32 standard output handle?

I used the code example I provided above, then called setvbuf(stdout, NULL, _IONBF, 4096) to set non-buffered output and got the desired result.



Related Topics



Leave a reply



Submit