59

I'm looking for a way that I can parse command line arguments into my WPF application with just a way of reading the value of the argument that the user passed.

As an example

application.exe /setTime 5

is there a way for me to have some code where I can just say:

MessageBox.Show(arg("setTime"));

Which will output 5

Working Solution

How to create smart WPF Command Line Arguments

Sandeep Bansal
  • 6,280
  • 17
  • 84
  • 126
  • 3
    Related [WPF Command Line](http://stackoverflow.com/questions/426421/wpf-command-line) – dee-see Feb 18 '12 at 17:28
  • 2
    Have you tried looking at codeplex? There are a lot of different implementation for command line parsing. – Vladimir Perevalov Feb 18 '12 at 17:30
  • 1
    There are many libraries to do handle command line args, see: http://stackoverflow.com/questions/491595/best-way-to-parse-command-line-arguments-in-c – H.B. Feb 19 '12 at 01:51
  • 2
    you can check out this using OnStartup of application https://stackoverflow.com/a/55667794/1115166 – Vikas Gupta Apr 13 '19 at 17:07

3 Answers3

126

The way I always do it is to specify the arguments as a "name"/"value" pair e.g.

myprogram.exe -arg1 value1 -arg2 value2

This means that when you parse the command line you can put the argument/value pairs in a Dictionary with the argument as the key. Then your arg("SetTime") will become:

MessageBox.Show(dictionary["SetTime"]);

(Obviously you don't want the actual dictionary to be public.)

To get the arguments in the first place you can use:

string[] args = Environment.GetCommandLineArgs();

This will return all the arguments so you will need to parse the array in steps of two (after first checking that the length is a multiple of two + 1):

The first element of the array is the name of the executing program - MS Learn - so your loop needs to start from one:

for (int index = 1; index < args.Length; index += 2)
{
     dictionary.Add(args[index], args[index+1]);
}

This loops in steps of two as you define each argument is a pair of values: the identifier and the actual value itself, e.g.

my.exe -arg1 value1 -arg2 value2

Then you can simply see if the argument is specified by seeing if the key -arg1 is in the dictionary and then read it's value:

string value;
if (dictionary.TryGetValue(arg, out value))
{
    // Do what ever with the value
}

This means you can have the arguments in any order and omit any arguments you don't want to specify.

The only drawback with this method is if you have a flag like -debug (for example) which could be logically implemented with the presence or absence of the flag will need to be specified as -debug true (or 1 or on), but it does simplify things if you have flags that do require values (like configuration file paths, database connection strings etc.)

MHN
  • 103
  • 2
  • 7
ChrisF
  • 134,786
  • 31
  • 255
  • 325
  • 1
    Working, was a lot simple than I thought it was. Thanks a lot – Sandeep Bansal Feb 18 '12 at 17:53
  • 4
    What if uneven number of parameters are given? To avoid the exception use for (int index = 1; index < args.Length - 1; index += 2) – J Pollack Jan 09 '13 at 19:50
  • @JPollack - if you have an uneven number of arguments then something is missing so you must report an error. – ChrisF Jan 09 '13 at 22:56
  • 3
    I don't believe each argument is a pair of values. It's your software so you decide what the various arguments mean. They are values separated by spaces. See the MDSN page about it. And to see them all just use this: Console.WriteLine("{0}", String.Join(", ", Environment.GetCommandLineArgs())); – Action Dan Jun 10 '16 at 09:53
  • @ActionDan - you define the arguments to be paired valued - the identifier and the the value - e.g. `my.exe -arg1 value1 -arg2 value2` etc. – ChrisF Jun 10 '16 at 10:00
  • 6
    @ChrisF - that is your design decision, this answer suggests that is the only way the system works, which is false. e.g you can simply do this my.exe -dothis -dothat without needing values and even the use of the - before an argument is your design decision. The arguments are not specified in pairs, and so any developer is free to do as they please. The answer implies otherwise. Alternatively you can use my.exe -dothis:haha -dothat:hehe it's all about how you want to design your software. You answered the question though no doubt about it. My comment is there to help expand possibilities. – Action Dan Jun 11 '16 at 21:13
  • +1 for a comprehensive answer. Another use-case is to add compatibility for your app to respond to Windows' "open with" using a routine that can cope with the first Arg (actually the 2nd element, thanks for noting that) is a file name that your app can use. – CAD bloke Oct 15 '16 at 07:15
8

There's another way to do this in WPF. Here's an article about it, and here's the steps to take:

First, you open App.xaml and you add Startup="Application_Startup" after the StartupUri="Window1.xaml", so your App.xaml will look like this:

<Application x:Class="ParametersForWPF.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml"
    Startup="Application_Startup">
    <Application.Resources>
    </Application.Resources>
</Application>

Then function Application_Startup will automatically be added to your App.xaml.cs file:

public partial class App : Application
{
    private void Application_Startup(object sender, StartupEventArgs e)
    {

    }
}

Now inside this function you can check the args sent to the application. An example to do this is:

private void Application_Startup(object sender, StartupEventArgs e)
{
    foreach(string s in e.Args)
    {
        MessageBox.Show(s);
    }
}

If you need them as a Dictionary then you could easily implement ChrisF's answer inside the Application_Startup function.

Paul Karam
  • 4,052
  • 8
  • 30
  • 53
  • I think it would be better to override OnStartup instead of using an event handler. Same reason as stated here: https://stackoverflow.com/a/3670912/5491112 – Brian Warren Jul 15 '20 at 19:02
2

this is how i handle both types of of arguments for example

myapp.exe -my-flag -another-flag -value-flag "Hello World"

Dictionary<string, string> arguments = new Dictionary<string, string>()

//e from StartupEventArgs e

for (int index = 0; index < e.Args.Length; index += 2)
{
    if(e.Args.Length == index+1 || e.Args[index + 1].StartsWith("-"))
    {
        arguments.Add(e.Args[index], string.Empty);
        index--;
    }
                    

    if (e.Args.Length >= index + 1 && !e.Args[index + 1].StartsWith("-"))
        arguments.Add(e.Args[index], e.Args[index + 1]);
}

You can could then check your values like so.

if(arguments.ContainsKey("my-flag")){
   arguments.TryGetValue("value-flag", valueFlag)
}