我在WinMain中有以下片段,我从控制台启动这个GUI应用程序.我想将输出重定向到启动我的应用程序的控制台.我得到"句柄无效".GetStdHandle()之后的错误.
但是,如果我使用AllocConsole而不是AttachConsole,它可以正常工作.另外,如果我使用STD_ERROR_HANDLE而不是STD_OUTPUTHANDLE,那么fprintf(stderr,"errror")工作正常.
我看到一个博客条目有同样的问题,但没有解决方案.我在64位Windows 7上使用vc 2010编译器.
谢谢!
bConsole = AttachConsole(ATTACH_PARENT_PROCESS) != FALSE;
if (bConsole)
{
int fd = 0;
long lStdOut;
lStdOut = (long)GetStdHandle(STD_OUTPUT_HANDLE);
fd = _open_osfhandle(lStdOut, _O_TEXT);
if (fd > 0)
{
*stdout = *_fdopen(fd, "w");
setvbuf(stdout, NULL, _IONBF, 0 );
}
}
printf("Test!!!!!!!!!!!!");
Run Code Online (Sandbox Code Playgroud)
AttachConsole确实将您的流程与控制台关联,但stdout已经打开(并连接到旧句柄,无论它是什么).
stdout直接覆盖是一个糟糕的主意.相反,你必须freopen("CONOUT$", "w", stdout);得到stdout去到控制台.
但是还有很多其他细节.看看我的问题从cygwin shell启动时写入stdout的地方是什么,没有重定向来解决问题中的问题,然后询问有关某些极端情况的问题.最后是一个包含所有内容的代码示例.
一个的Windows子系统进程(即一个有WinMain)不会有STDOUT,STDERR或STDIN,除非有人专门给一个上推出。假设是因为它是Windows程序,所以您正在通过Windows与之交互。
即GetStdHandle不会将句柄返回到STDOUT,因为您没有STDOUT。
要给它一个,可以这样启动它:
winprog.exe > output.txt 2>&1
Run Code Online (Sandbox Code Playgroud)
如果以这种方式启动,它将同时具有STDOUT和STDERR,它们都将进入命名文件。
正如其他用户已经指出的那样,AttachConsole将为您提供一个控制台(最近的unix / linux等效为TTY),但不会为您提供STDOUT。如果您想要一个,则必须将其设置为单独的步骤。如果您希望它成为控制台,您也可以拥有它。
另一方面,默认情况下,控制台子系统程序(带有的一个main)会将STDIN,STDOUT和STDERR都设置为控制台。您可以从控制台中分离该进程,并根据需要关闭它们。