从cygwin shell启动时写入stdout的位置是什么,没有重定向

Ben*_*igt 14 cygwin stdout

我有一个应用程序,我们称之为myapp.exe,这是双模式控制台/ GUI,内置为/ SUBSYSTEM:WINDOWS(有一个小的3KB垫片myapp.com使cmd.exe等待显示新提示.)

如果我从命令提示符启动:

  • myapp - > cmd.exe运行运行myapp.exe的myapp.com.stdout最初是一个独立的控制台,通过使用AttachConsole,freopen("CONOUT$", "w", stdout)我的输出显示在命令框中.好
  • myapp.exe - > cmd.exe显示提示太早(已知问题),否则与之前相同.不是正常的使用场景.
  • myapp > log- > stdout是一个文件,正常使用std::cout最终在文件中.好

如果我从Windows资源管理器启动:

  • myapp.com - >创建控制台,stdout是控制台,输出进入控制台.使用/ SUBSYSTEM:CONSOLE用于整个程序的结果相同,只是我myapp.com在控制台中唯一的进程时添加了一个暂停.不是正常的使用场景.
  • myapp.exe- > stdout是一个NULL句柄,我检测到这个并挂钩std::cout到GUI.好

如果我从Matlab shell启动:

  • system('myapp')或者system('myapp.com')system('myapp.exe')- >对于所有三种变型中,标准输出通过管道输送到MatLab的.好

如果我从cygwin bash shell启动:

  • ./myapp.com - >就像从cmd.exe启动一样,输出显示在命令框中.好
  • ./myapp- >(bash发现./myapp.exe). 这是破案.stdout是一个非NULL句柄,但输出无处可去.这是从bash运行程序的正常情况,需要修复!
  • ./myapp > log - >就像从带有文件重定向的cmd.exe启动一样.好
  • ./myapp | cat - >与文件重定向类似,但输出最终在控制台窗口中.好

有没有人知道cygwin在启动/ SUBSYSTEM:WINDOWS进程时设置为stdout以及如何绑定std::cout它?或者至少告诉我如何找出我从哪个手柄回来GetStdHandle(STD_OUTPUT_HANDLE)

我的程序是用Visual C++ 2010编写的/clr,如果有任何重要的话.操作系统是Windows 7 64位.

编辑:请求的其他信息.

CYGWIN环境变量为空(或不存在).

GetFileType()回报FILE_TYPE_UNKNOWN. GetLastError()回报6 (ERROR_INVALID_HANDLE).无论我是在打电话之前还是之后检查都没关系AttachConsole().

但是,如果我只是忽略无效的句柄,freopen("CONOUT$", "w", stdout)那么一切都很好.我只是错过了区分(被破坏的)控制台输出和文件重定向的方法,并GetFileType()提供了这一点.

编辑:最终代码:

bool is_console(HANDLE h)
{
    if (!h) return false;

    ::AttachConsole(ATTACH_PARENT_PROCESS);

    if (FILE_TYPE_UNKNOWN == ::GetFileType(h) && ERROR_INVALID_HANDLE == GetLastError()) {
        /* workaround cygwin brokenness */
        h = ::CreateFile(_T("CONOUT$"), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
        if (h) {
            ::CloseHandle(h);
            return true;
        }
    }

    CONSOLE_FONT_INFO cfi;
    return ::GetCurrentConsoleFont(h, FALSE, &cfi) != 0;
}


bool init( void )
{
    HANDLE out = ::GetStdHandle(STD_OUTPUT_HANDLE);

    if (out) {
        /* stdout exists, might be console, file, or pipe */
        if (is_console(out)) {
#pragma warning(push)
#pragma warning(disable: 4996)
            freopen("CONOUT$", "w", stdout);
#pragma warning(pop)
        }
        //std::stringstream msg;
        //DWORD result = ::GetFileType(out);
        //DWORD lasterror = ::GetLastError();
        //msg << result << std::ends;
        //::MessageBoxA(NULL, msg.str().c_str(), "GetFileType", MB_OK);
        //if (result == FILE_TYPE_UNKNOWN) {
        //  msg.str(std::string());
        //  msg << lasterror << std::ends;
        //  ::MessageBoxA(NULL, msg.str().c_str(), "GetLastError", MB_OK);
        //}
        return true;
    }
    else {
        /* no text-mode stdout, launch GUI (actual code removed) */
    }
}
Run Code Online (Sandbox Code Playgroud)

ak2*_*ak2 3

GetFileType ()函数允许区分某些类型的句柄,特别是控制台、管道、文件和损坏的句柄。