C++ AllocConsole() 不显示 cout

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15543571/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:28:26  来源:igfitidea点击:

AllocConsole() not displaying cout

c++dll

提问by madziikoy

I have a DLL where I use AllocConsole() and cout to display data for debugging purposes.
It used to work fine but since I updated my compiler (Visual Studio 2012) to the latest the dll just shows the console but not the prints/couts.
I am out of idea's as to why this is happening.
Any idea's?

我有一个 DLL,我在其中使用 AllocConsole() 和 cout 来显示用于调试目的的数据。
它曾经可以正常工作,但自从我将编译器(Visual Studio 2012)更新到最新版本后,dll 只显示控制台,而不显示打印/输出。
我不知道为什么会这样。
有任何想法吗?

Part of my code

我的代码的一部分

__declspec(dllexport) INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
    switch(Reason)
    {
    case DLL_PROCESS_ATTACH:    
        AllocConsole();

        DisableThreadLibraryCalls(hDLL);

        //
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourAttach(&(PVOID&)pSend, MySend);
        if(DetourTransactionCommit() == NO_ERROR)
             cout << "[" << MySend << "] successfully detoured." << endl;

But nothing gets displayed.

但什么也没有显示。

回答by Vladimir Sinenko

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;

回答by Turtlefight

After allocating a new console via AllocConsole(), you need to re-open the standard streams (stdout, stderr, stdin) before you can use them.

通过 分配新的控制台后AllocConsole(),您需要重新打开标准流 ( stdout, stderr, stdin) 才能使用它们。

You can do so by using freopen(in newer versions of Visual Studio you need to use freopen_s) Example:

您可以使用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);

If you want to use the deprecated freopenyou can disable the warningby #defineing _CRT_SECURE_NO_WARNINGS.

如果要使用已弃用的freopen,可以通过ing禁用警告#define_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:

如果您还想使用宽字符流(std::wcoutstd::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);

Additionally, if you tried to use one of the streams before re-opening them, they will have the std::ios_base::badbitand std::ios_base::failbitset 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::ios_base::badbitstd::ios_base::failbit将设置在它们的 中iostate,因此后续的写入/读取将被忽略。
您可以使用 重置流状态.clear(),之后您可以再次从/向流读取/写入:

std::cout.clear();
std::cin.clear();

Heres a full example of re-opening all the streams after AllocConsole():

下面是在 之后重新打开所有流的完整示例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();
}

回答by Willy

This works using vs2015 with the line std::cout.clear()

这适用于使用 vs2015 的行std::cout.clear()

if (!AllocConsole())
    MessageBox(NULL, L"The console window was not created", NULL, MB_ICONEXCLAMATION);

FILE* fp;

freopen_s(&fp, "CONOUT$", "w", stdout);

printf("Hello console on\n");

std::cout.clear();

std::cout << "Cout line one." << std::endl;

cout << "Cout line two." << std::endl;

MessageBox(NULL, (L"Pause to see console output."), (L"Pause Here"), MB_OK | MB_SYSTEMMODAL | MB_ICONEXCLAMATION);

fclose(fp);

if (!FreeConsole())
    MessageBox(NULL, L"Failed to free the console!", NULL, MB_ICONEXCLAMATION);