AllocConsole() not displaying cout

AllocConsole() not displaying cout

本文关键字:displaying cout not AllocConsole      更新时间:2023-10-16

我有一个DLL,我使用AllocConsole()和cout来显示数据用于调试目的。
它曾经工作得很好,但自从我更新了我的编译器(Visual Studio 2012)到最新的dll只是显示控制台,而不是打印/计数。
我不知道为什么会发生这种事。
知道的吗?

部分代码

__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;

但是没有显示

我隐约记得您可能需要将标准输出重定向到控制台。我可能是错的(因为你的代码之前工作):

AllocConsole();
freopen("CONOUT$", "w", stdout);
std::cout << "This works" << std::endl;

通过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,您可以通过#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::badbitstd::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();
}

使用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 onn");
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);