我想做一个 C#可以作为 CLI 或 GUI 应用程序运行的程序,具体取决于传递给它的标志。这能做到吗?
我发现了这些相关的问题,但它们并没有完全涵盖我的情况:
最佳答案
Jdigital's answer指向Raymond Chen's blog ,这就解释了为什么您不能拥有既是控制台程序又是非控制台的应用程序 *
程序:操作系统需要在程序开始运行之前知道要使用哪个子系统。一旦程序开始运行,返回并请求其他模式为时已晚。
Cade's answer指向an article about running a .Net WinForms application with a console .它使用了调用 AttachConsole
的技术。程序开始运行后。这具有允许程序写回启动程序的命令提示符的控制台窗口的效果。但是那篇文章中的评论指出了我认为的一个致命缺陷:子进程并没有真正控制控制台。控制台继续代表父进程接受输入,父进程不知道它应该等待子进程完成运行,然后再使用控制台做其他事情。
陈文指向an article by Junfeng Zhang that explains a couple of other techniques .
第一个是 devenv 使用的。它的工作原理是实际上有两个程序。一个是 devenv.exe,它是主要的 GUI 程序,另一个是 devenv.com,它处理控制台模式的任务,但如果它以非控制台方式使用,它会将其任务转发给 devenv.exe 并退出。该技术依赖于 Win32 规则,即当您键入不带文件扩展名的命令时,com 文件会在 exe 文件之前被选择。
Windows Script Host 在这方面有一个更简单的变体。它提供了两个完全独立的二进制文件,wscript.exe 和 cscript.exe。同样,Java 为控制台程序提供 java.exe,为非控制台程序提供 javaw.exe。
俊峰的第二个技巧就是ildasm所使用的。他引用了 ildasm 的作者在使其在两种模式下运行时所经历的过程。最终,这是它的作用:
仅仅调用
FreeConsole
是不够的使第一个实例不再是控制台程序。这是因为启动程序 cmd.exe 的进程“知道”它启动了一个控制台模式的程序并正在等待该程序停止运行。调用 FreeConsole
会使 ildasm 停止使用控制台,但不会使父进程开始使用控制台。所以第一个实例会自动重启(我想有一个额外的命令行参数)。当您调用
CreateProcess
,有两个不同的标志可以尝试, DETACHED_PROCESS
and CREATE_NEW_CONSOLE
,其中任何一个都将确保第二个实例不会附加到父控制台。之后,第一个实例可以终止并允许命令提示符恢复处理命令。这种技术的副作用是当你从 GUI 界面启动程序时,仍然会有一个控制台。它会在屏幕上短暂闪烁然后消失。
我认为 Junfeng 的文章中关于使用 editbin 更改程序的控制台模式标志的部分是一个红鲱鱼。您的编译器或开发环境应该提供一个设置或选项来控制它创建的二进制文件类型。之后应该不需要修改任何东西。
那么,底线是 您可以拥有两个二进制文件,也可以让控制台窗口瞬间闪烁 .一旦你决定哪个是较小的邪恶,你就可以选择实现。
*
我说非控制台而不是 GUI 因为否则它是一个错误的二分法。仅仅因为程序没有控制台并不意味着它有 GUI。服务应用程序就是一个典型的例子。此外,一个程序可以有一个控制台和窗口。
关于c# - 一个可执行文件可以既是控制台又是 GUI 应用程序吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/493536/