通过 分配新控制台后AllocConsole()
,您需要重新打开标准流(stdout
、stderr
、stdin
)才能使用它们。
您可以通过使用freopen
(在较新版本的 Visual Studio 中您需要使用freopen_s
)示例:
FILE *fDummy;
freopen_s(&fDummy, "CONIN$", "r", stdin);
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONOUT$", "w", stdout);
如果要使用已弃用的freopen
,可以通过ing禁用警告。#define
_CRT_SECURE_NO_WARNINGS
如果您还想使用宽字符流(std::wcout
、std::wcerr
等...),则需要调用SetStdHandle()
为您的进程设置新的输出句柄。CreateFile()
您可以通过使用CONOUT$
/CONIN$
作为文件名调用来获取所需的文件句柄:
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);
此外,如果您在重新打开它们之前尝试使用其中一个流,它们将在它们的 中std::ios_base::badbit
设置 和std::ios_base::failbit
,iostate
因此后续的写入/读取将被忽略。
您可以使用 重置流状态.clear()
,之后您可以再次读取/写入流:
std::cout.clear();
std::cin.clear();
下面是重新打开所有流之后的完整示例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();
}