locked
Running Command line or Windows Form application through Arguments RRS feed

  • Question

  • I am looking to create an application that run Windows Form based version of it, if no Command line argument is pass, otherwise it run Command line Version of it. Simple ?

    To explain my question:
    I need an MyApp.exe. If I double click on it's icon on my Desktop, it open up the Windows Form. But if I open it through Command Prompt with something like this:

    C:\MyApp.exe cgi

    then it should do all stuff within command line.

    Hope I make sense :).
    Sumit Gupta http://www.vikasumit.com http://www.sumitgupta.net
    Wednesday, December 23, 2009 5:34 PM

Answers

  • Here's a full working example.  Just take your Windows Form project, and change Program.cs to:


    namespace CSharpWinFormsProject
    {
        using System;
        using System.Runtime.InteropServices;
        using System.Windows.Forms;
    
        static class Program
        {
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            static extern bool FreeConsole();
    
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                string[] args = Environment.GetCommandLineArgs();
                // We'll always have one argument (the program's exe is args[0])
                if (args.Length == 1)
                {
                    // Run windows forms app
                    FreeConsole();
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new Form1());
                }
                else
                {
                    Console.WriteLine("We'll run as a console app now");
                    Console.ReadKey();
                }
            }
        }
    }
    

    Reed Copsey, Jr. - http://reedcopsey.com
    • Proposed as answer by Reed Copsey, JrMVP Wednesday, December 23, 2009 6:33 PM
    • Marked as answer by Vikasumit Wednesday, December 23, 2009 6:34 PM
    Wednesday, December 23, 2009 6:24 PM

All replies

  • You can use this code to do just that. You could put this in the Main method or anywhere else in your application.

    string
    [] args = Environment.GetCommandLineArgs();
    foreach (string arg in args)
    { // do stuff }


    Dewayne Dodd - Landshark Software "Please make sure to 'Mark As Answer' if this answer solves your question"
    • Proposed as answer by LandsharkDaddy Wednesday, December 23, 2009 5:58 PM
    Wednesday, December 23, 2009 5:44 PM
  • Hello,

    I see your point, but the problem is my application is little interactive. Let me explain it further.

    My application will run on Windows server 2008.
    When a user do RemoteDesktop to Server he will double click and run the application to "Configure" it through Windows Form. But otherwise the application will be configured in Task Schedular. (here your case might work).

    But the twist is client ask that he can run the same EXE from command line and see the output.

    so here is what needed

    C:\> myapp.exe :: open the Windows Forms, and prompt for next command.
    C:\> myapp.exe cgi :: Will be called from Task schedular produce no output
    C:\> myapp.exe cgi -v produce output when run in CONSOLE/command prompt

    I am able to achieve everything by making a Console application and then checking the arguments. but when I run the application by double clicking it it open the "COnsole" in background, which I don't need.

    Hope it is clearer now ?
    Sumit Gupta http://www.vikasumit.com http://www.sumitgupta.net
    Wednesday, December 23, 2009 6:02 PM
  • You can do this.

    Basically, make your application a Console Application.

    When you start, if there are no command line arguments, you can use P/Invoke to call FreeConsole (which removes the console window), then show your form.

    If there is an argument, do you processing instead.

    You can also, optionally, remove the console output for the task scheduler, but this is not required.  It is perfectly acceptable for a scheduled task to show console output, so I would just leave it in place to simplify your life.





    Reed Copsey, Jr. - http://reedcopsey.com
    Wednesday, December 23, 2009 6:06 PM
  • Hello,

    Thanks for your reply.

    But I am fairly new to this type of work, can you give few line sample on FreeConsole stuff? I never use Kernel32.dll stuff and never use it before.


    Sumit Gupta http://www.vikasumit.com http://www.sumitgupta.net
    Wednesday, December 23, 2009 6:15 PM
  • Hello,

    I try the method like this

    ...
    
    
    [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", SetLastError = true)]
    static extern int FreeConsole(); 
    static void GUIStartup()
    {
    FreeConsole();
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
    }
    
    ...
    However when I run the application in GUI mode it keep the Console open in background. like modal window. So this doesn't work.

    Sumit Gupta http://www.vikasumit.com http://www.sumitgupta.net
    Wednesday, December 23, 2009 6:23 PM
  • Here's a full working example.  Just take your Windows Form project, and change Program.cs to:


    namespace CSharpWinFormsProject
    {
        using System;
        using System.Runtime.InteropServices;
        using System.Windows.Forms;
    
        static class Program
        {
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            static extern bool FreeConsole();
    
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                string[] args = Environment.GetCommandLineArgs();
                // We'll always have one argument (the program's exe is args[0])
                if (args.Length == 1)
                {
                    // Run windows forms app
                    FreeConsole();
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new Form1());
                }
                else
                {
                    Console.WriteLine("We'll run as a console app now");
                    Console.ReadKey();
                }
            }
        }
    }
    

    Reed Copsey, Jr. - http://reedcopsey.com
    • Proposed as answer by Reed Copsey, JrMVP Wednesday, December 23, 2009 6:33 PM
    • Marked as answer by Vikasumit Wednesday, December 23, 2009 6:34 PM
    Wednesday, December 23, 2009 6:24 PM
  • Hello Reed,

    Thanks for code. I already/and did what you suggest. You can run your sample EXE from command line and you will see what I mean.

    Regards
    Sumit Gupta http://www.vikasumit.com http://www.sumitgupta.net
    Wednesday, December 23, 2009 6:29 PM
  • Ops!!!

    I just rerun my application and found it working. Thanks :).

    Actually I was first running it from Cmd command, and not by double clicking.. from where ti works fine ...
    Sumit Gupta http://www.vikasumit.com http://www.sumitgupta.net
    Wednesday, December 23, 2009 6:34 PM
  • Okay - I think I understand what you're attempting now.

    You can rework this - instead of making it a Console application, set it to be a Windows Application.  Then, if you want to run as a console, we'll turn the Windows App into a console by creating a console on the fly.  The "tricky" part here is attaching to your parent console, so if you run from a command prompt, we will attach to it, instead of making a new console (and if you don't, you need to free your console).

    The full code becomes:

    namespace CSharpWinFormsProject
    {
        using System;
        using System.Runtime.InteropServices;
        using System.Windows.Forms;
        static class Program
        {
            [DllImport("kernel32")]
            static extern bool AllocConsole();
    
            const uint ATTACH_PARENT_PROCESS = 0x0ffffffff; 
    
            [DllImport("kernel32.dll", SetLastError = true)]
            static extern bool AttachConsole(uint dwProcessId);
    
            [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
            static extern bool FreeConsole();
    
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                bool createdConsole = false;
                string[] args = Environment.GetCommandLineArgs();
                // We'll always have one argument (the program's exe is args[0])
                if (args.Length == 1)
                {
                    // Run windows forms app
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new Form1());
                }
                else
                {
                    // First, try to attach to parent process console.
                    // If that fails, create our own console
                    if (!AttachConsole(ATTACH_PARENT_PROCESS))
                    {
                        AllocConsole();
                        createdConsole = true;
                    }
                    Console.WriteLine("We'll run as a console app now");
                    Console.ReadKey();
    
                    // At end, free our console
                    if (createdConsole)
                        FreeConsole();
                }
    
            }
        }
    }
    
    

    Reed Copsey, Jr. - http://reedcopsey.com
    Wednesday, December 23, 2009 6:41 PM
  • Thanks for your Reply. This is better code indeed, but later one does work for my need after all it is just a server schedular application. But your code will do for other project. I am really a lover of Application run from both mode from Single EXE.


    Sumit Gupta http://www.vikasumit.com http://www.sumitgupta.net
    Friday, January 1, 2010 2:46 PM