Windows应用程序,可选择保持附加到控制台

时间:2011-11-06 22:18:21

标签: windows visual-c++ console

我有一个Windows应用程序(用C编写,用MSVC Express版编译,32位模式),它有两种主要的操作模式:

  • 窗口模式 - 创建一个窗口,并在其中绘制内容(即分形)。
  • 基准测试模式 - 以--benchmark作为参数运行时,不要创建窗口,只是将一些基准统计信息打印到stdout。

在开发过程中,我编译为Console应用程序,并使用SDL创建窗口并执行其他GUI功能。因此基准模式运行正常(没有创建窗口),图形模式只有一个挥之不去的控制台窗口。

然而,对于我的发布编译,我启用了Windows子系统而不是控制台。 (如this question中所述)。除非我突然发现我无法再运行基准测试,否则这种方法很有效。 :○

我只是想知道,应用程序是否有办法在运行时选择(例如,根据它给出的命令行)使用哪种子系统行为?

我已经在Windows中对EXE文件进行了一些实验(资源管理器,记事本,winword),当使用像“/?”这样的参数运行时,它们似乎都没有打印到控制台。 (大多数Windows控制台应用程序支持)。所以它看起来不像,但我觉得这里有一个特殊的伎俩值得问一下。

更新。看起来,不,你不能。谢谢你的答案。

其他学术问题。这是否意味着子系统选项在EXE标题中标记,并且操作系统会检查这个并设置窗口或将其连接到从其运行的控制台?我对EXE加载知之甚少,但我很想知道这里的一些细节。

结论。我认为有四种好的解决方案(加上两种半解决方案,总共五种:p)可供选择:

  1. 使用控制台子系统,但在GUI模式下运行时使用FreeConsole。
  2. 使用Windows系统,并在基准模式下运行时使用AllocConsole。如果fractal.exe是从现有控制台运行的,那就不完美了,所以我将其视为解决方案的一半; - )。
  3. 每个子系统只有一个可执行文件,fractal.exe和fractalgui.exe。
  4. 有两个(或更多)可执行文件,其中一个执行工作并将其传递给另一个,以便在控制台或适当的窗口中显示。需要考虑如何划分程序以及如何在程序之间进行通信。
  5. 另一个半解决方案:让fractalgui.exe将基准测试打印到标准输出,然后将其输送到只打印它的实用程序。
  6. 我尚未选择,但我倾向于#3。

    感谢Matteo和smerlin的想法!

3 个答案:

答案 0 :(得分:2)

应用程序无法在运行时选择她的子系统(有一些非常难看的解决方法,但那些都充满了怪癖)。

然后这个问题的一般解决方案是拥有一个控制台应用程序,如果需要,它将启动你的gui应用程序

对于您的基准案例,它只会打印您的基准统计信息。

示例设置:
- fractalgui.exe(子系统:windows)
- fractal.exe(子系统:控制台)

*用户桌面上的快捷方式链接到fractalgui.exe
*如果用户从控制台启动fractal.exe,则fractal exe启动fractalgui.exe
*如果用户启动fractal.exe --benchmark,它或者自己进行基准测试(如果可以将此基准逻辑添加到另一个可执行文件中)并将信息直接打印到控制台,或者 - 如果不可能 - 则需要启动fractalgui.exe --nogui --benchmark。这里的棘手案例是将你的输出从fractalgui.exe输入到fractal.exe,这样你就可以在适当的控制台上打印它。有几种方法可以做到这一点,例如命名管道(有一些方法以某种方式启动fractalgui.exe,你可以在那里使用stdout / cout,数据将通过管道传输到fractal.exe的stdout,但我不记得这是多么精确地工作了(编辑:也许this有效))。最简单的方法是启动fractalgui.exe --nogui --benchmark > mylogfile,然后在fractalgui.exe完成后打印mylogfile(因为如果输出被重定向到文件,fractalgui.exe的stdout / cout将起作用),但是你不会得到“实时”输出,因为当fractalgui.exe已经完成时,所有输出都将打印在控制台上。

答案 1 :(得分:2)

要添加到@ smerlin的答案,另一个经常看到的方法(在我在评论中链接的文章中引用)是将您的应用程序标记为控制台应用程序,但在释放控制台时(使用FreeConsole)你确定你不需要它。

这就是ildasm的作用,但它的缺点是在应用程序启动和调用FreeConsole之间短暂闪烁控制台。

  

其他学术问题。这是否意味着子系统选项在EXE标头中标记,操作系统检查这个并设置Window或将其连接到运行的控制台?我对EXE加载知之甚少,但我很想知道这里的一些细节。

是的,加载程序检查PE头并根据此处指定的子系统设置所有内容。

与* NIX方法形成对比:没有可执行文件是“特殊的”,每个人都有一个工作stdin / stdout / stderr;想要显示某些内容的应用程序将调用Xlib的相应功能。缺点是如果您正在启动的应用程序正常使用控制台,GUI应用程序不知道,因此系统必须询问您是否还要生成终端仿真器或丢弃标准流并等待它生成窗口(显然捷径存储了这些信息)。

答案 2 :(得分:0)

我描述了一种在my question here中实现这一目标的技术。

Matteo已经提到了.com技巧,但这只是可行解决方案的一部分。