如何把std::cout标准输出重定向到vs2019的输出窗口中

代码

#include <iostream>
#include <io.h>
#include <fcntl.h>
#include <process.h>
#include <Windows.h>
#include<thread>

int pipeHandles[2];
const int kBufferSize = 4096;
void ReadFunc(int readhandle)
{
    char buf[kBufferSize];
    int readBtyes;
    do {
        readBtyes = ::_read(readhandle, buf, kBufferSize);        
        buf[readBtyes] = 0;
        ::OutputDebugStringA(buf);
    } while (readBtyes);
}

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    AllocConsole();             //create console
    ShowWindow(GetConsoleWindow(), SW_HIDE);  //we hide the window, But it will flashes once
    FILE* reopenOut = nullptr;    
    FILE* repoenErr = nullptr;
    freopen_s(&reopenOut, "CONOUT$", "w+t", stdout); //if we don't want to use console,we can alse use files
    freopen_s(&repoenErr, "CONOUT$", "w+t", stderr); //  freopen_s(&repoenErr, "err.log", "w+t", stderr); 
    ::_pipe(pipeHandles, kBufferSize, _O_TEXT);
    int orignalH = ::_dup(_fileno(stdout)); //we don't care about the orignal handle
    ::_dup2(pipeHandles[1], _fileno(stdout));
    ::_dup2(pipeHandles[1], _fileno(stderr));
    std::thread threadRead(&ReadFunc, pipeHandles[0]);    
    
    for (int i = 0; i < 2; ++i)
    {
        std::cout << "hello" << i << std::endl;
        std::cerr << "Error: hello" << i << std::endl;
        printf("HelloPrintf%d\n", i);        
        fprintf(stderr, "ErrorP:Hello%d\n", i);
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    
    fclose(reopenOut);          //we must colse file firt
    fclose(repoenErr);          //the order is very important
    _close(pipeHandles[1]);    
    threadRead.join();
    _close(pipeHandles[0]);

    return 0;
}

参考

Windows进程内标准输出重定向及其在程序调试上的应用

Creating a Child Process with Redirected Input and Output

Use SetStdHandle to redirect stdout and stderr

pipe

dup2

How to Capture OutputDebugString to console

运作流程

  • 创建控制台,创建之后就可以使用控制台的buffer了
  • 重新打开stdout,这样std :: cout才可以正确的输出数据
  • 创建管道来重定向std :: cout
  • 使用dup2函数将std :: cout重定向到管道写句柄
  • 使用另一个线程读取管道数据,即重定向的std :: cout
  • 按照顺序释放资源

我的理解

  • 我需要此功能是因为我想在vs2019输出窗口中看到std :: cout文本
  • 在进入main函数之前,stdout 和 std::cout已经创建并和当时的stdhandle绑定好了,所以我们在main函数之后调用setStdHandle修改handle是不会修改std::cout的绑定的,除非我们能在进入main之前绑定好,就如微软例子中子线程重定向一样。
  • 但是我们可以使用dup2函数来重定向, 虽然这样我必须要freopen stdout, 不然重定向会失败。
  • 释放资源的顺序非常重要
  • 需要理解管道pipe,和重定向dup2
  • 我们可以使用文件代替控制台,但这并不重要
  • 我曾尝试过不创建控制台窗口和文件,不调用freopen, 通过setStdHandle直接重定向失败,但是我很希望有简单完美的方法,希望高人指点。
发布了8 篇原创文章 · 获赞 4 · 访问量 1704
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览