Подтвердить что ты не робот

AllocConsole() не отображает cout

У меня есть DLL, где я использую AllocConsole() и cout для отображения данных для целей отладки.
Он работал нормально, но поскольку я обновил свой компилятор (Visual Studio 2012) до последней версии, DLL просто показывает консоль, но не отпечатки /couts.
Я не понимаю, почему это происходит.
Любая идея?

Часть моего кода

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

Но ничего не отображается.

4b9b3361

Ответ 1

Я смутно помню, что вам может потребоваться перенаправить stdout на консоль. Возможно, я ошибаюсь (поскольку у вас раньше работал ваш код):

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

Ответ 2

Это работает с использованием 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);

Ответ 3

После выделения новой консоли через 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::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();
}