一个可执行文件可以既是控制台又是 GUI 应用程序吗? [英] Can one executable be both a console and GUI application?

查看:15
本文介绍了一个可执行文件可以既是控制台又是 GUI 应用程序吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想制作一个可以作为 CLI 运行的 C# 程序或 GUI 应用程序取决于传递给它的标志.可以这样做吗?

I want to make a C# program that can be run as a CLI or GUI application depending on what flags are passed into it. Can this be done?

我发现了这些相关问题,但它们并没有完全涵盖我的情况:

I have found these related questions, but they don't exactly cover my situation:

推荐答案

Jdigital 的回答 指向 RaymondChen 的博客,解释了为什么你不能同时拥有一个既是控制台程序又是非控制台程序的应用程序*:操作系统需要在程序开始运行之前知道 使用哪个子系统.一旦程序开始运行,返回并请求其他模式为时已晚.

Jdigital's answer points to Raymond Chen's blog, which explains why you can't have an application that's both a console program and a non-console* program: The OS needs to know before the program starts running which subsystem to use. Once the program has started running, it's too late to go back and request the other mode.

凯德的回答 指向 一篇关于使用控制台运行 .Net WinForms 应用程序的文章.它使用了调用 AttachConsole 之后的技术程序开始运行.这具有允许程序写回启动程序的命令提示符的控制台窗口的效果.但那篇文章中的评论指出了我认为的一个致命缺陷:子进程并没有真正控制控制台.控制台继续代表父进程接受输入,而父进程进程不知道它应该等待子进程完成运行,然后才能使用控制台做其他事情.

Cade's answer points to an article about running a .Net WinForms application with a console. It uses the technique of calling AttachConsole after the program starts running. This has the effect of allowing the program to write back to the console window of the command prompt that started the program. But the comments in that article point out what I consider to be a fatal flaw: The child process doesn't really control the console. The console continues accepting input on behalf of the parent process, and the parent process is not aware that it should wait for the child to finish running before using the console for other things.

Chen 的文章指向 张俊峰的一篇文章,解释了其他几种技术.

Chen's article points to an article by Junfeng Zhang that explains a couple of other techniques.

第一个是 devenv 使用的.它的工作原理是实际上有两个程序.一个是 devenv.exe,它是主要的 GUI 程序,另一个是 devenv.com,它处理控制台模式的任务,但如果它用于非类似控制台的方式,它将其任务转发到 devenv.exe 并退出.该技术依赖于 Win32 规则,即当您键入不带文件扩展名的命令时,com 文件会在 exe 文件之前被选择.

The first is what devenv uses. It works by actually having two programs. One is devenv.exe, which is the main GUI program, and the other is devenv.com, which handles console-mode tasks, but if it's used in a non-console-like manner, it forwards its tasks to devenv.exe and exits. The technique relies on the Win32 rule that com files get chosen ahead of exe files when you type a command without the file extension.

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

There's a simpler variation on this that the Windows Script Host does. It provides two completely separate binaries, wscript.exe and cscript.exe. Likewise, Java provides java.exe for console programs and javaw.exe for non-console programs.

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

Junfeng's second technique is what ildasm uses. He quotes the process that ildasm's author went through when making it run in both modes. Ultimately, here's what it does:

  1. 该程序被标记为控制台模式二进制文件,因此它始终以控制台开头.这允许输入和输出重定向正常工作.
  2. 如果程序没有控制台模式命令行参数,它会自行重新启动.

仅仅调用 FreeConsole 来使第一个实例不再是控制台程序是不够的.那是因为启动程序的进程 cmd.exe 知道"它启动了一个控制台模式程序并正在等待程序停止运行.调用 FreeConsole 会使 ildasm 停止使用控制台,但它不会使父进程启动使用控制台.

It's not enough to simply call FreeConsole to make the first instance cease to be a console program. That's because the process that started the program, cmd.exe, "knows" that it started a console-mode program and is waiting for the program to stop running. Calling FreeConsole would make ildasm stop using the console, but it wouldn't make the parent process start using the console.

所以第一个实例会自行重新启动(我想有一个额外的命令行参数).当您调用 CreateProcess 时,有两个不同的标志可以尝试,DETACHED_PROCESSCREATE_NEW_CONSOLE,其中任何一个都将确保第二个实例不会附加到父控制台.之后,第一个实例可以终止并允许命令提示符继续处理命令.

So the first instance restarts itself (with an extra command-line parameter, I suppose). When you call CreateProcess, there are two different flags to try, DETACHED_PROCESS and CREATE_NEW_CONSOLE, either of which will ensure that the second instance will not be attached to the parent console. After that, the first instance can terminate and allow the command prompt to resume processing commands.

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

The side effect of this technique is that when you start the program from a GUI interface, there will still be a console. It will flash on the screen momentarily and then disappear.

Junfeng 的文章中关于使用 editbin 更改程序的控制台模式标志的部分,我认为是一个红鲱鱼.您的编译器或开发环境应该提供一个设置或选项来控制它创建的二进制文件类型.之后应该不需要修改任何东西.

The part in Junfeng's article about using editbin to change the program's console-mode flag is a red herring, I think. Your compiler or development environment should provide a setting or option to control which kind of binary it creates. There should be no need to modify anything afterward.

最重要的是,您可以有两个二进制文件,也可以让控制台窗口瞬间闪烁.一旦您决定哪个危害较小,您就可以选择实现方式.

The bottom line, then, is that you can either have two binaries, or you can have a momentary flicker of a console window. Once you decide which is the lesser evil, you have your choice of implementations.

* 我说的是 non-console 而不是 GUI 因为否则这是一个错误的二分法.仅仅因为程序没有控制台并不意味着它有 GUI.服务应用程序就是一个典型的例子.此外,程序可以有一个控制台窗口.

* I say non-console instead of GUI because otherwise it's a false dichotomy. Just because a program doesn't have a console doesn't mean it has a GUI. A service application is a prime example. Also, a program can have a console and windows.

这篇关于一个可执行文件可以既是控制台又是 GUI 应用程序吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆