C# application both GUI and commandline

C#WinformsUser InterfaceCommand Line

C# Problem Overview


I currently have an application with a GUI.

Would it be possible to use this same application from the commandline (without GUI and with using parameters).

Or do I have to create a separate .exe (and application) for the commandline tool?

C# Solutions


Solution 1 - C#

  1. Edit your project properties to make your app a "Windows Application" (not "Console Application"). You can still accept command line parameters this way. If you don't do this, then a console window will pop up when you double-click on the app's icon.
  2. Make sure your Main function accepts command line parameters.
  3. Don't show the window if you get any command line parameters.

Here's a short example:

[STAThread]
static void Main(string[] args)
{
    if(args.Length == 0)
    {
        Application.Run(new MyMainForm());
    }
    else
    {
        // Do command line/silent logic here...
    }
}

If your app isn't already structured to cleanly do silent processing (if all your logic is jammed into your WinForm code), you can hack silent processing in ala CharithJ's answer.

EDIT by OP Sorry to hijack your answer Merlyn. Just want all the info here for others.

To be able to write to console in a WinForms app just do the following:

static class Program
{
    // defines for commandline output
    [DllImport("kernel32.dll")]
    static extern bool AttachConsole(int dwProcessId);
    private const int ATTACH_PARENT_PROCESS = -1;

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        // redirect console output to parent process;
        // must be before any calls to Console.WriteLine()
        AttachConsole(ATTACH_PARENT_PROCESS);

        if (args.Length > 0)
        {
            Console.WriteLine("Yay! I have just created a commandline tool.");
            // sending the enter key is not really needed, but otherwise the user thinks the app is still running by looking at the commandline. The enter key takes care of displaying the prompt again.
            System.Windows.Forms.SendKeys.SendWait("{ENTER}");
            Application.Exit();
        }
        else
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new QrCodeSampleApp());
        }
    }
}

Solution 2 - C#

In your program.cs class keep the Main method as it is but add string[] Args to the main form. For example...

    [STAThread]
    static void Main(string[] Args)
    {
        ....
        Application.Run(new mainform(Args));
    }

In mainform.cs constructor

    public mainform(string[] Args)
    {
        InitializeComponent();

        if (Args.Length > 0)
         {
             // Do what you want to do as command line application.
             // You can hide the form and do processing silently.
             // Remember to close the form after processing.
         }
    }

Solution 3 - C#

I am new to c# programming. But I improvised the code hints from OP and Merlyn. The issue I faced when using their code hint was that the argument length is different when I call app.exe by double click on app.exe or when I call it from CMD. When app.exe is run as CLI from CMD then app.exe itself becomes the first arguments. Below is my improvised code which works satisfactory both as GUI double click of app.exe and as CLI from CMD.

[STAThread]
    static void Main(/*string[] args*/)
    {
        string[] args = Environment.GetCommandLineArgs();
        Console.WriteLine(args.Length);
        if (args.Length <= 1)
        {
            //calling gui part
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new ACVSAppForm());
        }
        else
        {
            //calling cli part                
            string opt = args[1];
            //Console.WriteLine(args[0]);                
            if(opt == "LastBuild")
            {
                if(args.Length == 3)
                {
                    var defSettings = Properties.Settings.Default;
                    defSettings.CIBuildHistPath = args[2];
                }
                else
                {
                    //
                }
                CIBuildParser cibuildlst = new CIBuildParser();
                cibuildlst.XMLParser();
            }
        }
        
    }

I hope this helps someone. The only drawback of my solution is when the app.exe is run as GUI, it will open a CMD as console output window. But this is OK for my work.

Solution 4 - C#

You may need to structure your Application as a Console Application, identify what you do on "Actions" - like clicking of the button - into separate class, include a form that can be shown if there were no command line arguments supplied, and handle events by routing them to the common methods in your "Action" class.

Solution 5 - C#

I think it is possible, just set your subsystem to "console", you will see a console window as well as the GUI window.

But in order to accept commands from the console window, I guess you will have to create an extra thread to do it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPeeHaaView Question on Stackoverflow
Solution 1 - C#Merlyn Morgan-GrahamView Answer on Stackoverflow
Solution 2 - C#CharithJView Answer on Stackoverflow
Solution 3 - C#MFzView Answer on Stackoverflow
Solution 4 - C#ArunView Answer on Stackoverflow
Solution 5 - C#Bill YanView Answer on Stackoverflow