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();
}
freopen("CONIN$", "r", stdin);
also works as expected. – Ronen