Rico Suter's blog.
 


Have you ever had the need to use an application (.exe) as a command line tool when started in the console (cmd.exe) and as GUI application when started from the Explorer shell? This article explains a possible implementation for this requirement.

To be clear: I didn’t find the perfect solution; a Windows .NET application is either a console application or a Windows application. Either type can be used in the opposite mode, but both variants have some drawbacks.

This article describes the solution which I think has the least disadvantages. The solution works by defining the application as console application and show the WPF window if the application is not executed in a console. The only drawback I’ve found is that the console window is shown for some milliseconds at application start.

The other approach is to define the application as Windows application, but then you will have a lot of problems when using the application in console mode, e.g. the application is started in a second window, the output is not printed to the original console and the console does not wait until the application has executed because Windows forked out the process. This is why I prefer the first solution.

Implementation

The following steps describe how to implement such a “hybrid” application:

  1. Create new WPF application project
  2. Add a Program.cs file with the following content:

    public static class Program
    {
        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        static extern bool FreeConsole();
        
        [STAThread]
        public static int Main(string[] args)
        {
            if (args != null && args.Length > 0)
            {
                // TODO: Add your code to run in command line mode
                Console.WriteLine("Hello world. ");
                Console.ReadLine();
                return 0;
            }
            else
            {
                FreeConsole();
                var app = new App();
                return app.Run();
            }
        }
    }
    
  3. Add a constructor in App.xaml.cs and call InitializeComponent():

    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }
    }
    
  4. Open project settings

    1. Select “Program.Main” as application entry point
    2. Change the type of the project to “Console application”

Final thoughts

Even if there are some solutions, I think it is better to provide two different applications which call shared assemblies. This way you avoid all the mentioned issues and do not have to live with the drawbacks of the available workarounds.

Further reading

For more information on this topic, head to the following sources:



Discussion