我有一个应用程序,我们称之为myapp.exe,它是双模控制台/gui,内置为/subsystem:windows(有一个很小的3kb填充程序myapp.com,它会使cmd.exe等待显示新的提示。)
如果我从命令提示符启动:
-
myapp
->cmd.exe运行myapp.com,其中运行myapp.exe。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是一个空句柄,我检测到它并挂起
STD::
到一个图形用户界面。好啊
如果我从matlab shell启动:
-
system('myapp')
或
system('myapp.com')
或
system('myapp.exe')
->对于所有三种变体,stdout都通过管道传输到matlab。好啊
如果我从cygwin bash shell启动:
-
./myapp.com
->就像从cmd.exe启动一样,输出显示在命令框中。好啊
-
./myapp
->(bash发现
./myapp.exe
)
这是破箱子
. stdout是一个非空的句柄,但输出不去任何地方。这是从bash运行程序的正常情况,需要修复!
-
./myapp > log
->就像通过文件重定向从cmd.exe启动一样。好啊
-
./myapp | cat
->类似于文件重定向,但输出最终出现在控制台窗口上。好啊
是否有人知道Cygwin在启动/subsystem:windows进程时将什么设置为stdout,以及如何绑定
STD::
去吗?或者至少告诉我如何找出我要从哪种方式得到回报
GetStdHandle(STD_OUTPUT_HANDLE)
?
我的程序是用Visual C++ 2010编写的,没有
/clr
如果这在任何方面都很重要。操作系统是Windows7 64位。
编辑:请求的其他信息。
cygwin环境变量为空(或不存在)。
GetFileType()
退货
FILE_TYPE_UNKNOWN
.
GetLastError()
退货
6 (ERROR_INVALID_HANDLE)
. 我打电话之前还是之后都查对了
AttachConsole()
.
但是,如果我只是忽略了无效的句柄,
freopen(“conout$”,“w”,stdout)
然后一切都很好。我只是缺少一种区分(总线化)控制台输出和文件重定向的方法,以及
获取文件类型()
前提是。
编辑:最终代码:
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) */
}
}