一尘不染

一个可执行文件可以既是控制台又是GUI应用程序?

c#

我想制作一个可以作为CLI或GUI应用程序运行的C#程序,具体取决于传递给它的标志是什么。能做到吗?

我发现了以下相关问题,但它们并不能完全满足我的情况:


阅读 332

收藏
2020-05-19

共1个答案

一尘不染

Jdigital的答案指向Raymond
Chen的博客
,该博客解释了为什么不能同时拥有控制台程序和非控制台*程序的应用程序:操作系统需要
在程序开始运行 要使用的子系统 之前 就知道。程序开始运行后,现在返回并请求其他模式为时已晚。

Cade的答案指向有关使用控制台运行.Net
WinForms应用程序的文章
。它使用AttachConsole程序开始运行后调用的技术。这样的效果是允许程序写回到启动程序的命令提示符的控制台窗口。但是该文章中的评论指出了我认为是致命的缺陷:
子进程实际上并不控制控制台。 控制台继续代表父进程接受输入,并且父进程不知道在使用控制台进行其他操作之前,它应等待子进程完成运行。

Chen的文章指向Zhang Junfeng
Zhang的文章,它解释了其他两种技术

首先是 devenv的 用途。它实际上有两个程序。一个是主界面GUI程序 devenv.exe ,另一个是处理控制台模式任务的
devenv.com ,但是如果以非控制台方式使用它,则它将其任务转发给 devenv.exe
和退出。该技术依赖于Win32规则,当您键入不带文件扩展名的命令时,将在 exe 文件之前选择 com 文件。 __

Windows脚本宿主对此有一个更简单的变化。它提供了两个完全独立的二进制文件 wscript.execscript.exe 。同样,Java
为控制台程序提供 java.exe ,为非控制台程序提供 javaw.exe

俊峰的第二种技术是 ildasm 使用的技术。他引用了 ildasm 的作者在两种模式下运行时所经历的过程。最终,这是它的作用:

  1. 该程序被标记为控制台模式二进制文件,因此它始终从控制台开始。这样可以使输入和输出重定向正常进行。
  2. 如果程序没有控制台模式命令行参数,它将重新启动自身。

仅仅通过调用FreeConsole使第一个实例不再是控制台程序是不够的。这是因为启动程序 cmd.exe
的进程“知道”它已启动控制台模式程序,并且正在等待程序停止运行。调用FreeConsole将使 ildasm 停止使用控制台,但不会使父进程
开始 使用控制台。

因此,第一个实例会自行重启(我想带有一个额外的命令行参数)。当您调用时CreateProcess,有两个不同的标志可以尝试使用,分别是DETACHED_PROCESSCREATE_NEW_CONSOLE,这两个标志将确保第二个实例不会附加到父控制台。此后,第一个实例可以终止并允许命令提示符恢复处理命令。

这种技术的副作用是,当您从GUI界面启动程序时,仍然会有一个控制台。它将在屏幕上短暂闪烁,然后消失。

我认为, Junfeng 文章中有关使用 editbin
更改程序的控制台模式标志的部分是一个红色的鲱鱼。您的编译器或开发环境应提供一个设置或选项来控制它创建哪种二进制文件。此后无需再进行任何修改。

最重要的是, 您可以具有两个二进制文件,也可以具有控制台窗口的瞬时闪烁 。一旦确定哪个是较小的邪恶,就可以选择实现。

*我说的 是非控制台 而不是 GUI,
因为这是错误的二分法。仅仅因为程序没有控制台并不意味着它具有GUI。服务应用程序就是一个很好的例子。另外,程序可以具有控制台 窗口。

2020-05-19