How to make an application as both GUI and Console application?


This is another common asked question. But it is a Win32 question.


In Windows GUI applications and Console applications are very different. GUI applications have at least one window, and a message loop, but no standard in/out/error. Console applications have standard in/out/error, but no window, no message loop. An application is either a GUI application or Console application, but not both.


Some people want their application behaves differently depending on input. If there are inputs, the application behaves like Console application. If there is no input, it behaves like GUI applications.


Just like devenv (Visual Studio) and ildasm.


How do they do that?


VisualStudio and ildasm achieve this very differently.


In VisualStudio case, there are actually two binaries: devenv.com and devenv.exe. Devenv.com is a Console app. Devenv.exe is a GUI app. When you type devenv, because of the Win32 probing rule, devenv.com is executed. If there is no input, devenv.com launches devenv.exe, and exits itself. If there are inputs, devenv.com handles them as normal Console app.


In ildasm case, there is only one binary: ildasm.exe. It is first compiled as a GUI application. Later editbin.exe is used to mark it as console subsystem. In its main method it determines if it needs to be run as console mode or GUI mode. If need to run as GUI mode, it relaunches itself as a GUI app.


 

Comments (12)

  1. consoled says:

    So is that the same for cmd.exe? Or does the OS do something special? If I launch it from Win+R it creates a new window, but if I then call cmd again from within that console itself, it creates a new cmd instance and redirects its stdio to the same window.

  2. Are there any issues with simply renaming a .NET console .exe to .com?

  3. Eric,

    See my another post "Name of your-app.exe". Basically we won’t be able to find itself in non-default domain because we only probe .dll/.exe

    Consoled,

    It is nothing special for cmd.exe. Console apps by default re-use parent’s console, unless you specify a flag in CreateProcess. If launched from explorer, because explorer is a GUI app, a new console is created for cmd.exe (because cmd.exe is a console app). If launched from cmd.exe itself, it re-uses the existing console.

  4. Nate W says:

    Note that when launching ildasm from explorer.exe, it’s not unusual to see a console window flicker briefly.

    The problem is that the OS decides whether or not your app needs a console before your app begins to execute, based on information in the .exe header. The gui-vs-console decision is made at build time, not execution time. If you attempt to have one executable fulfill both roles, you will have to put up with quirks.

    If you build as a console app, and get run from a GUI tool (e.g. explorer), a console window will be created before your application begins to execute. If you build as a GUI app, the OS will detach your application from the console before your own code begins to execute. The former is only slightly inelegant – you can close that console window easily. The latter is a more substantial problem because you cannot re-attach to the console from which the application was spawned. By the time your code starts executing, the console may already have issued a C:> prompt and the user could be typing their next command – or worse, your application may have been run from a batch file and the next command in the batch is already piping information into a log file before your application begins executing.

    Far as I can tell, the devenv.com / devnenv.exe solution seems to be the most elegant.

  5. I’m not clear on why editbin is needed.

    You mention fundamental features of a GUI app: "GUI applications have at least one window, and a message loop," but there’s absolutely nothing stopping a console application having these. The fact that you have a stdin and stdout doesn’t stop you from also opening windows.

    There’s no real need to use editbin. I just used VS.NET 2003 to build a standard Win32 console application. I then put enough of the code from the good old ‘Generic’ sample in the PSDK to get a window up and running. Works fine. I have a window that behaves normally, and also a console window that behaves normally.

    This has always worked. The console vs windows app is mainly a matter of a linker switch and supplying the right kind of entry point.

  6. Everything has a story.

    Here is what the author of ildasm says:

    ——————————————-

    From:

    To: Junfeng Zhang

    Subject: RE: Mixed console/windows app

    It’s actually quite a story.

    Initially, ILDASM was a console app that by default dumped the disassembly text to the console window, or launched GUI when prompted by the command line option. People started complaining that when they launch ILDASM in GUI mode from a console window, it doesn’t release the console window (of course it doesn’t — it’s a console app).

    OK, so I’ve made ILDASM a GUI app and GUI was made the default mode. Launched from a console window in GUI mode, ILDASM immediately released the console. People started complaining that they want to dump the disassembly text to a console window.

    OK, so I added console window popping up whenever console dump was ordered. ILDASM released the original console, popped up new console when ordered, and dumped the disassembly text there. People started complaining that they can’t redirect console dump to a file. Why it’s preferable to do "ildasm MyApp.dll /text > MyApp.il" instead of "ildasm MyApp.dll /out=MyApp.il", still remains mystery to me.

    OK, so I’ve made ILDASM a GUI-disguised-as-console app. It releases the console window in GUI mode, it dumps the disassembly text to the console window when ordered, and you can redirect this console dump to a file. People started complaining that when ILDASM is launched from Windows Explorer, it momentarily flashes a console window before going into GUI mode (Nate is not actually the first one to notice this effect). Sorry, folks, I’m afraid I can’t fix that without breaking some of the above.

    Thanks,

  7. Uriel Mondrowicz says:

    Hi All,

    I have seen this thread on Junfeng Zhang’s blog which is related to an ongoing issue I have.

    Zhang, thank you very much for your post.

    I’m trying to build in C# a simple tool that should be used in dual mode:

    1. Windows Application when called without any arguments (or simply

    double-clicked)

    2. Console Application when called from a command line with some arguments

    I could create a parent console application that runs from a command line

    (and sends its output to the stdout console) when it is called with some

    arguments.

    If it detects that no arguments were entered (args.Length == 0) it opens a

    windows form using the frmGUI.ShowDialog() method.

    My main problem is that when clicking on the tool executable to run it as a

    win GUI, it will open a black console window for a second, dissapear, and

    then show the GUI form.

    This is very annoying, and I’m sure there is a way to resolve this black

    screen issue. Although it has the same bahavior as the ILDASM as described by it’s author.

    I tried using FreeConsole() method in my entry point just before checking

    the args but it still shows the black console for a second.

    I cannot use the MSDEV approach as I have to keep it in only one executable standalone file.

    I know that this thread is quite old, hoever I was wondering if anyone here could find a solution to this problem or can point me to some other sources.

    You can contact me directly using the email below.

    Thanks in advance,

    Uriel Mondrowicz.

    urielmon@hotmail.com

  8. This is an OS issue and there is probably nothing you can do about it.