GUI 程序中的控制台输出






4.26/5 (14投票s)
描述了如何将Windows程序的输出显示到控制台窗口。
引言
如果您使用MFC应用程序向导创建Windows程序,则程序不会显示已发送到标准输出或标准错误句柄的文本输出。
在某些时候,出于诊断或功能目的,输出的可见性可能是可取的。或者您可能希望添加程序的命令行操作。为了与命令行操作保持一致,文本应自动输出到命令/dos窗口。
本文介绍了使用EditBin实用程序激活Windows(或GUI)程序的控制台模式操作。(对于那些想要一些源代码的人,该程序包含一个与cout
流对象重定向相关的EditBin程序。)
获取文本输出的替代方法
从命令提示符运行Windows程序,并使用命令窗口的重定向功能重定向输出:“>out.txt”和“2>errors.txt”
使用::SetStdHandle()
重新分配标准输出和错误输出句柄以将其通过管道传输或发送到另一个文件。此过程似乎很难实现。
您可以编写一个控制台程序,重新映射提供给生成的程序的stdout
、stdin
和stderr
。生成的程序将是您想要收集输出的程序。
Microsoft EditBin实用程序
EditBin.exe位于Visual Studio 6的VC98\bin子路径中。
这个不起眼的工具提供了从Visual C++ 6(或Visual Basic 6)编写的Windows模式程序启用文本控制台输出的关键。您可以将程序可执行文件在Windows模式和控制台模式之间切换。
- EditBin MyProgram.exe /SUBSYSTEM:CONSOLE
- EditBin MyProgram.exe /SUBSYSTEM:WINDOWS
在构建过程中包含Editbin实用程序
文章图片显示了Visual Studio 6项目设置,展示了在添加到构建过程后Microsoft EditBin实用程序的显示方式。
“构建后步骤”选项卡允许您在最终可执行文件上输入命令。图片显示了示例
editbin /SUBSYTEM:CONSOLE $(OUTDIR)\iTHXTool.exe
程序的控制台版本的副作用
控制台窗口将与应用程序窗口一起出现。如果您想查看诊断信息,这可能是理想的选择。如果您从命令提示符启动程序,命令窗口将显示标准输出和标准错误文本。
您可能需要创建应用程序的两个副本:一个严格的GUI程序和一个命令行版本。这些程序将包含相同的编译代码,但其中一个将使用EditBin工具进行修改。
Microsoft的帮助条目还提到文件句柄0、1和2(这应该以某种方式等同于stdout
和stderr
)不会重新分配,因为这些值是在Windows程序的CRT启动时分配的。(但是,您可以使用vc98\CRT\source目录中的文件修改CRT。)
关于VS6项目设置的最后一个观察结果……
您可能会注意到在MFC向导生成的应用程序的“项目设置链接”选项卡下显示“/subsystem:windows”。但是,仅仅将此条目更改为/subsystem:console就无法获得控制台输出。
一些用于重定向cout的代码
此处的源代码程序提供了一个重定向cout
流对象的示例。由于某些原因,源代码没有正确重定向stdout
文件句柄,尽管各个网站都描述了stdout
应该是可重定向的。
应用程序包含一个文本编辑器窗口,该窗口每隔十秒钟会自动填充一天中的时间。程序依赖于通过ReadFile
调用在线程内运行的管道输出。
重定向的核心发生在主应用程序对象的初始化中。对于所有相关的代码,搜索“2005年4月”字符串,这将引导您找到对标准向导生成的代码的所有代码修改。
初始化步骤
rval = CreatePipe(&hRead,&hWrite,0,0); rval = SetStdHandle(STD_OUTPUT_HANDLE,hWrite); //Now assign hWrite to stdout, cout FILE *fp; int hConHandle; long lStdHandle; lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE); hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); fp = _fdopen( hConHandle, "w" ); // The stdout reassignment didn't seem to work // *stdout = *fp; // redefine the stdout to point to the pipe setvbuf( fp, NULL, _IONBF, 0 ); // Filebuf object attached to "test.dat" filebuf *fb = new filebuf(_fileno(fp ) ); cout = fb;
此程序展示了如何进行重定向。请注意,文本的缓冲(用于插入RTF文档的文本)的设计并不健壮。代码在某些情况下(并非所有情况下)都绕过了使用Microsoft EditBin.exe工具的需要。
最好将数据写入内存文件,而不是通过管道发送数据。这样就不需要创建线程来监视管道的输出了。无论如何,_open_osfhandle
未能将内存映射句柄转换为典型的文件句柄(在hConHandle
中)。
结论
Windows GUI开发并不方便地支持访问cout
、cerr
、stdout
或stderr
。在窗口程序的直接控制下获取这些内容可能很困难。至少存在一些技巧可以在真正需要时获取信息。