如何在不调用AllocConsole()的情况下初始化subsystem=windows程序中的stdout/stderr?

dkqlctbz  于 2022-12-22  发布在  Windows
关注(0)|答案(1)|浏览(188)

因此,当尝试在Windows GUI应用程序中使用stdin/stdout/stderr流时,通常需要调用AllocConsole(或AttachConsole)来初始化这些流以供使用。这里有很多帖子介绍调用AllocConsole后需要做的事情(即在相应的流上使用freopen_s等)。
我有一个程序,我想把stdout和stderr重定向到一个匿名管道。我有一个工作示例,我调用:

AllocConsole();

    FILE* fout;
    FILE* ferr;

    freopen_s(&fout, "CONOUT$", "r+", stdout);
    freopen_s(&ferr, "CONOUT$", "r+", stderr);

    HANDLE hreadout;
    HANDLE hwriteout;
    HANDLE hreaderr;
    HANDLE hwriteerr;

    SECURITY_ATTRIBUTES sao = { sizeof(sao),NULL,TRUE };
    SECURITY_ATTRIBUTES sae = { sizeof(sae),NULL,TRUE };
    CreatePipe(&hreadout, &hwriteout, &sao, 0);
    CreatePipe(&hreaderr, &hwriteerr, &sae, 0);

    SetStdHandle(STD_OUTPUT_HANDLE, hwriteout);
    SetStdHandle(STD_ERROR_HANDLE, hwriteerr);

这个代码段成功地将stdout和stderr设置为匿名管道的写入端,我可以捕获数据。
然而调用AllocConsole会产生一个Conhost.exe-这是弹出到屏幕上的实际黑色窗口。我没有使用这个,最重要的是,我希望避免在我的程序下创建一个子conhost.exe进程。
所以问题是,我怎样才能欺骗Windows,让它认为它有一个控制台连接/手动设置初始的stdout和stderr文件流,以便我可以重定向它们,因为我已经做了?我已经看了调试器中的AllocConsole调用以及GetStdHandle和SetStdHandle,试图了解正在发生的事情,但我的RE技能是缺乏的。
如果没有AllocConsole,freopen_s调用会失败,错误6,无效句柄。GetStdHandle也返回一个NULL句柄。调用SetStdHandle成功(基于它的返回代码和调用GetLastError),但是这看起来并没有在我需要的地方设置好东西,因为我在管道中没有收到任何输出。
有什么想法吗?

iecba09b

iecba09b1#

使用SetStdHandle函数将管道句柄值指定给STD_INPUT_HANDLE和STD_OUTPUT_HANDLE。

相关问题