WinAPI-如何将程序的所有标准输出和外部DLL重定向到Win32标准输出句柄?

问题描述 投票:0回答:1

我希望能够将Windows应用程序的所有标准输出重定向到Win32标准输出句柄,而不是使用控制台句柄。

关于上下文,Emacs Win32常见问题解答这样说:

显式使用控制台句柄(CON或CON :)而不是stdin和stdout的程序不能用作Emacs的子进程,它们也不能在shell模式下工作。[...]没有方便的方法用于Emacs或在shell模式下使用的任何shell,以将此类进程的输入和输出从控制台重定向到输入和输出管道。唯一的解决方法是使用不直接使用控制台的程序的不同实现。(https://www.gnu.org/software/emacs/manual/html_node/efaq-w32/Subprocess-hang.html

我遇到了FAQ所描述的问题:从Emacs启动时,程序将运行,但是在Emacs的shell窗口中,直到程序退出之前,它的所有输出都不会显示,就好像stdout已缓冲并且没有刷新一样在运行时。如果从cmd.exe或ConEmu运行,则同一程序将按预期实时输出stdout。

我想要完成的是使程序的所有输出都出现在Emacs shell中,这样一来,我可以在打印后立即跳转到编译器错误的位置。我愿意重写程序的源代码来完成此任务。我想知道通过使用“ stdin和stdout”而不是“控制台的句柄”来完成此操作需要哪些“不同的实现”细节。

据我了解:

  1. Windows中有多种I / O,包括C运行时(printf等)和Win32层(ReadFile等)。
  2. [我假设“ stdin和stdout”是指可以由STD_INPUT_HANDLE修改的STD_OUTPUT_HANDLESetStdHandle()
  3. 由程序加载的外部DLL将继承C运行时stdinstdout管道,但这是在程序初始化时发生的,在对SetStdHandle()的任何调用之前,因此您需要做一些其他事情来重定向他们的输出。
  4. 我尝试使用此代码:

#include <windows.h>
#include <cstdlib>

int main()
{
    HANDLE hStdout = CreateFile(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    HANDLE hStdin = CreateFile(L"CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    SetStdHandle(STD_OUTPUT_HANDLE, hStdout);
    SetStdHandle(STD_ERROR_HANDLE, hStdout);
    SetStdHandle(STD_INPUT_HANDLE, hStdin);

    std::cout << "Hello, world." << std::endl;
    printf("Hello, world.\n");
    std::cin.get();

    return 0;
}

这具有所需的效果,但仅在与重定向代码相同的二进制文件中的printfstd::cout的用法上。我的程序加载了一个使用printf的外部DLL,并且其输出均未重定向。

而且,我不想使用AllocConsole()或类似的东西,因为这会打开一个单独的窗口,该窗口不与父进程(Emacs)集成。我想要的是重定向所有标准输出,以便它显示在运行程序的同一终端/控制台中,而不是显示在其他窗口中(如果有意义)。由于我不使用AllocConsole(),因此由于某些原因,像_open_osfhandle((long)hStdout, O_WRONLY|O_TEXT)这样的代码总是返回-1,因此看来我不能像dup2()所述使用here

另见:

我希望能够将Windows应用程序的所有标准输出重定向到Win32标准输出句柄,而不是使用控制台句柄。对于上下文,Emacs Win32 FAQ表示:...

c++ c windows printf
1个回答
0
投票

我使用了上面提供的代码示例,然后调用了setvbuf(stdout, NULL, _IONBF, 4096)来设置非缓冲输出并获得期望的结果。


推荐问答