尝试在Windows上重定向stdout和stderr-_fileno(stdout)返回-2

时间:2018-08-13 12:46:20

标签: c++ windows pipe

这是我的第一个问题!

我打算将一些可以正常工作的C ++代码从UNIX移植到Windows,这将通过管道将stdout和stderr重定向到自定义GUI组件。我需要它来显示来自第三方库的反馈,该库仅在GUI上将消息输出到stdout。

根据此答案https://stackoverflow.com/a/617158,此方法应该有效。实际上,来自链接的代码在使用Visual Studio 2017构建的全新命令行应用程序中按预期工作。但是,在我现有的GUI应用程序中,对_fileno(stdout)_fileno(stderr)的调用都返回-2期望值1和2中的任何一个,因此什么也没有发生。对相关功能进行硬编码1和2也不起作用。

任何人都可以解释

  • 确切的返回值-2是什么? (对此,谷歌搜索很多-没有成功)
  • 在没有控制台的情况下,是否有可能在Windows上实现我想要的功能?
  • 如果可能的话,有什么相关的步骤使它起作用?

为您提供信息,到目前为止,我已经收集了我在Linux和Mac OS上进行编程的主要经验,因此对于有经验的Windows用户而言,这可能是显而易见的。 GUI应用程序基于JUCE框架,因此我使用的是JUCE工具Projucer创建的自动生成的Visual Studio项目

2 个答案:

答案 0 :(得分:3)

与Unix类型的系统不同,在Windows中,控制台应用程序和GUI应用程序是两个不同的东西。 GUI应用程序没有stdin,stdout或stderr的概念-它们仅了解Windows,文本框等。

documentation for _fileno says

  

如果stdout或stderr与输出流不关联(对于   例如,在没有控制台窗口的Windows应用程序中,该文件   返回的描述符是-2。

因此,如果要使用stdout和stderr,则需要将应用程序构建为控制台应用程序(仍然可以使用GUI)。

另一种方法是继续将应用程序构建为GUI,但可以通过在应用程序开始时调用AllocConsole()来分配控制台(即,在WinMain()中要做的第一件事),然后然后关联stdout和stderr文件:

if(AllocConsole()){
    freopen("CONOUT$", "w", stdout);
    freopen("CONOUT$", "w", stderr);
}

答案 1 :(得分:1)

我使用AllocConsole方法@DodgyCodeException提出了建议。最后,我现在在GUI组件的构造函数中调用以下代码以启动控制台并立即将其隐藏,以使用户不会被空的控制台窗口所迷惑:

if(AllocConsole())
{ 
    freopen ("CONOUT$", "w", stdout); 
    freopen ("CONOUT$", "w", stderr); 
    ShowWindow (FindWindowA ("ConsoleWindowClass", NULL), false); 
}

这在运行时效果很好,例如这样,直到构造相应的GUI组件时才调用它。此外,这种方法使代码对我而言更具可重用性,因为将其包含在其他项目中并不需要添加源文件,而不必在意修改构建时间设置。