Windows GUI应用程序中重定向的标准输出上的WriteFile返回ERROR_NO_DATA

问题描述

编辑:刚刚发现这只是PowerShell控制台的问题。它似乎可以从cmd.exe运行。正在调查更多...

在Windows GUI(/ SUBSYstem:WINDOWS)应用程序中,附加或创建控制台相对容易,只需将WriteFile插入到stdout。 (如果要使用标准的C / C ++ API,例如How do I get console output in C++ with a Windows program?,可以参与其中,但是如果使用Win32 API WriteFile,这似乎很简单)。

但是我注意到重定向stdout时,该代码在控制台应用程序中工作正常,如果是GUI应用程序,则会炸毁。

下面是基本代码(或在https://github.com/billti/WinCons上查看完整的示例)。只需将以下内容作为头文件包括在内,WinMain实例化该类后不久,调用CreateConsole,则对Write的任何调用都将失败,并带有标记***错误–但仅在重定向输出时启动(例如myapp.exe > .\log.txt)。如果未重定向,它可以正常工作,并且在控制台应用程序中,任何一种方法都可以正常工作。

注意:附加到父控制台可能会导致交错输出混淆,但是确实可以。

任何想法如何解决这个问题?如何从非控制台Windows应用程序重定向标准输出才能正常工作?

#include <string>
 
class Log
{
public:
    void CreateConsole() {
        // In a console app,redirected or not,this returns a valid handle.
        // In a non-redirected GUI app,this returns NULL.
        // If redirected GUI (e.g. "winapp.exe > .\log.txt") this returns a valid handle.
        hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
        if (hStdOut == NULL || hStdOut == INVALID_HANDLE_VALUE) {
            // If launched from a console,then Attach work,else must Alloc.
            if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
                if (!AllocConsole()) {
                    throw std::exception("Failed to allocate a console");
                }
            }
            hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
            if (hStdOut == INVALID_HANDLE_VALUE || hStdOut == NULL) {
                throw std::exception("Invalid stdout");
            }
        }
        hasConsole = true;
    }
 
    void Write(const std::string& msg) {
        DWORD written = 0;
        DWORD err = 0;
        if (hasConsole) {
            if (!WriteFile(hStdOut,msg.c_str(),msg.length(),&written,nullptr)) {
                // *** If output is being redirected in a GUI app,this always fails with ***
                //   0xE8 ERROR_NO_DATA "The pipe is being closed."
                err = GetLastError();
                throw std::exception("Failed to write to console");
            }
        }
    }
 
private:
    bool hasConsole = false;
    HANDLE hStdOut = INVALID_HANDLE_VALUE;
};

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...