WPF: Supporting command line arguments and file extensions

Traditionally, handling command-line args in an app has been a simple case of reading arguments from the “int main()” function (or equivalent). In WPF this changes somewhat.

The usual setup is that you have your App.xaml.cs, which loads your initial window. While it’s the former that  has access to the arguments, it’s the latter that is likely to use them. So the steps are:

  1. In App.xaml.cs, catch the event that gives you the args.
  2. Store them somewhere.
  3. Access them from your main window.

Here’s one way to do it (demonstrating a single argument). Firstly, in App.xaml.cs:

    1: protected override void OnStartup(StartupEventArgs e)
    2: {
    3:     if (e.Args != null && e.Args.Count() > 0)
    4:     {
    5:         this.Properties["ArbitraryArgName"] = e.Args[0];
    6:     }
    7:  
    8:     base.OnStartup(e);
    9: }

Then in the main window, you can access Application.Current.Properties to get at your args. However, if this happens to be the name of a file you want to load, you should probably wait until after your window has finished loading so that you can react to that file load (eg; give an error, display data, etc):

    1: public MainContainer()
    2: {
    3:     InitializeComponent();
    4:  
    5:     // Make sure we handle command line args:
    6:     this.Loaded += new RoutedEventHandler(MainContainer_Loaded);
    7: }
    8:  
    9: void MainContainer_Loaded(object sender, RoutedEventArgs e)
   10: {
   11:     if (Application.Current.Properties["ArbitraryArgName"] != null)
   12:     {
   13:         string fname = Application.Current.Properties["ArbitraryArgName"].ToString();
   14:         // Act on the file...
   15:     }
   16: }

 

Launching via a double-click on a custom file type.

I created an application that supports a custom document format and I wanted a double-click on that document to open my application. I assumed that the application would open normally with the document presented as a command-line arg, but that’s not the case. Instead, it’s stored in the following tongue-twister:

AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData[0]

So, if you revisit the OnStartup method in App.xaml.cs, you can query this location and store it in the same way you did the command-line arg:

    1: protected override void OnStartup(StartupEventArgs e)
    2: {
    3:     // Check if this was launched by double-clicking a doc. If so, use that as the
    4:     // startup file name.
    5:     if (AppDomain.CurrentDomain.SetupInformation
    6:         .ActivationArguments.ActivationData != null
    7:     &&  AppDomain.CurrentDomain.SetupInformation
    8:         .ActivationArguments.ActivationData.Length > 0)
    9:     {
   10:         string fname = "No filename given";
   11:         try
   12:         {
   13:             fname = AppDomain.CurrentDomain.SetupInformation
   14:                     .ActivationArguments.ActivationData[0];
   15:             
   16:             // It comes in as a URI; this helps to convert it to a path.
   17:             Uri uri = new Uri(fname);
   18:             fname = uri.LocalPath;
   19:  
   20:             this.Properties["ArbitraryArgName"] = fname;
   21:  
   22:         }
   23:         catch (Exception ex)
   24:         {
   25:             // For some reason, this couldn't be read as a URI.
   26:             // Do what you must...
   27:         }
   28:     }
   29:  
   30:     base.OnStartup(e);
   31: }

Notice the little trick with using the “Uri” class; this is because the string you’ll see will look like this:

 

Avi

Comments

  • Anonymous
    November 04, 2008
    Include Prakash.Subramanian@yahoo.comI want to receive an email whenever newMicrosoft specific content is posted in this blog

  • Anonymous
    April 24, 2010
    Well add an sanity check for :AppDomain.CurrentDomain.SetupInformation.ActivationArguments != nullthanks,Srikanth.

  • Anonymous
    August 27, 2010
    Is there a way to debug the second part concerning the double-clicking of a custom file type created for your application?Thanks.

  • Anonymous
    August 29, 2010
    You should be able to debug it normally; just chuck a breakpoint in there. Any issues with that?

  • Anonymous
    May 10, 2012
    A few things I had to change to make it work:call base.OnStartup(e); in the beginning of the functionadd Srikanth's check for (AppDomain.CurrentDomain.SetupInformation.ActivationArguments != null) But it never got past that check :(  The file opened, but nothing else happened.  the messagebox below showed that howFar was always "123", even when I opened it from a file.  I'm using Windows 7 btw.       protected override void OnStartup(StartupEventArgs e)       {           string howFar = "1";           // Check if this was launched by double-clicking a file. If so, use that as the startup file name.           if (AppDomain.CurrentDomain != null)           {               howFar += "2";               if (AppDomain.CurrentDomain.SetupInformation != null)               {                   howFar += "3";                   if (AppDomain.CurrentDomain.SetupInformation.ActivationArguments != null)                   {                       howFar += "4";                       if (AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData != null)                       {                           howFar += "5";                           if (AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData.Length > 0)                           {                               howFar += "6";                               String fname = "No filename given";                               try                               {                                   fname = AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData[0];                                   // It comes in as a URI; this helps to convert it to a path.                                   Uri uri = new Uri(fname);                                   fname = uri.LocalPath;                                   this.Properties["FileThatCausedLaunch"] = fname;                               }                               catch                               {                                   // For some reason, this couldn't be read as a URI.                                   // Do what you must...                                   this.Properties["FileThatCausedLaunch"] = ""; // this will cause an exception when we try to read it, which will trigger our error message                               }                           }                           base.OnStartup(e);                       }                   }               }           }           MessageBox.Show(howFar);           base.OnStartup(e);       } // OnStartup

  • Anonymous
    May 10, 2012
    @hypehuman: Seems this might be caused by differences between a double-click on an EXE and a ClickOnce activation. Check out these two discussions (read the comments) and tell me if that helps:stackoverflow.com/.../challenges-with-associating-filesstackoverflow.com/.../wpf-click-once-double-click-file-to-launch-vs-2008