Search code examples
c#.netwpfwinforms

How do I create a C# app that decides itself whether to show as a console or windowed app?


Is there a way to launch a C# application with the following features?

  1. It determines by command-line parameters whether it is a windowed or console app
  2. It doesn't show a console when it is asked to be windowed and doesn't show a GUI window when it is running from the console.

For example,

myapp.exe /help
would output to stdout on the console you used, but
myapp.exe
by itself would launch my Winforms or WPF user interface.

The best answers I know of so far involve having two separate exe and use IPC, but that feels really hacky.


What options do I have and trade-offs can I make to get the behavior described in the example above? I'm open to ideas that are Winform-specific or WPF-specific, too.


Solution

  • Make the app a regular windows app, and create a console on the fly if needed.

    More details at this link (code below from there)

    using System;
    using System.Windows.Forms;
    
    namespace WindowsApplication1 {
      static class Program {
        [STAThread]
        static void Main(string[] args) {
          if (args.Length > 0) {
            // Command line given, display console
            if ( !AttachConsole(-1) ) { // Attach to an parent process console
               AllocConsole(); // Alloc a new console
            }
    
            ConsoleMain(args);
          }
          else {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
          }
        }
        private static void ConsoleMain(string[] args) {
          Console.WriteLine("Command line = {0}", Environment.CommandLine);
          for (int ix = 0; ix < args.Length; ++ix)
            Console.WriteLine("Argument{0} = {1}", ix + 1, args[ix]);
          Console.ReadLine();
        }
    
        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool AllocConsole();
    
        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool AttachConsole(int pid);
    
      }
    }