1

I can start my UWP app from windows command prompt or PowerShell. I've gotten some idea on how to read the arguments passed to the UWP app, as well. But, I have not been able to find any documentation on how to pass those arguments from App.xaml.cs file to the MainPage.xaml.cs.

For example, you can define an app execution alias - as shown below - for your UWP app, so you can launch it easily from cmd or powershell:

<Extensions>
    <uap5:Extension
      Category="windows.appExecutionAlias"
      StartPage="index.html">
      <uap5:AppExecutionAlias>
        <uap5:ExecutionAlias Alias="MyApp.exe" />
      </uap5:AppExecutionAlias>
    </uap5:Extension>
</Extensions>

You can then read arguments from the OnActivated event as shown below:

async protected override void OnActivated(IActivatedEventArgs args)
{
    switch (args.Kind)
    {
        case ActivationKind.CommandLineLaunch:
            CommandLineActivatedEventArgs cmdLineArgs = 
                args as CommandLineActivatedEventArgs;
            CommandLineActivationOperation operation = cmdLineArgs.Operation;
            string cmdLineString = operation.Arguments;
            string activationPath = operation.CurrentDirectoryPath;
……..
}

Question: From the above event in App.xaml.cs file, how do I pass the value of the string cmdLineString to MainPage.xaml.cs file? Example: I pass Hello World to command line. The App.xaml.cs file reads that argument. Now through my code, I want to pass that Hello World value to MainPage.xaml.cs file so I can assign it to, say, TextBlock.Text property in the main window.

Environment: VS2019 - ver 16.5.5, Windows 10 Pro - 1903

nam
  • 21,967
  • 37
  • 158
  • 332

2 Answers2

1

in UWP, parameters are usually passed between pages through navigation.

This piece of code roughly shows the structure of the OnActivated method:

protected override void OnActivated(IActivatedEventArgs args)
{
    Frame rootFrame = Window.Current.Content as Frame;

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (rootFrame == null)
    {
        // Create a Frame to act as the navigation context and navigate to the first page
        rootFrame = new Frame();
        rootFrame.NavigationFailed += OnNavigationFailed;
        // Place the frame in the current Window
        Window.Current.Content = rootFrame;
    }
    string commandParam = string.Empty;
    switch (args.Kind)
    {
        case ActivationKind.CommandLineLaunch:
            //get command parameter
            break;
        default:
            //do other things...
            break;
    }
    if (rootFrame.Content == null)
    {
        rootFrame.Navigate(typeof(MainPage), commandParam);
    }
    // Ensure the current window is active
    Window.Current.Activate();
}

After getting the command line parameters, the most important thing is in this line of code:

rootFrame.Navigate(typeof(MainPage), commandParam);

Through navigation, we can pass parameters to MainPage.

After this, we need to receive the parameter in the MainPage and process it:

MainPage.xaml.cs

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if(e.Parameter!=null && e.Parameter is string commandParam)
    {
        TestTextBlock.Text = commandParam;
    }
    base.OnNavigatedTo(e);
}

For more information about navigation, you can refer to this document

Richard Zhang
  • 7,523
  • 1
  • 7
  • 13
  • @RichardZhangMSFT Your suggestion seems more promising - specifically since (as you also mentioned): `in UWP, parameters are usually passed between pages through navigation.`. But it is working only when I take `rootFrame.Navigate(typeof(MainPage), commandParam);` line outside the `if (rootFrame.Content == null){…}` block . That seems to indicate that `(rootFrame.Content is not null`. Why? What could be a reason? – nam May 18 '20 at 16:24
  • Hello, according to your description, you start the application from the command line and pass parameters to `MainPage`. This is the first load. But there are still other situations, just like you start `Word` by opening a doc file, if the application is not open, then start the application first, and then open the file, if the application is already open (ie, rootFrame is not null), then open the file directly. If your application needs to take into account that the application has started, rather than just starting the application from the command line, please let me know. – Richard Zhang May 19 '20 at 01:19
  • @ RichardZhangMSFT In `VS2019` I just click on `Rebuild Solution`. Then I run the app from `Powershell` passing the parameter. So this is the first load, correct? I still like your solution since it seems to be the correct way of doing it. The only issue is the `if statement` block. There are some other choices such as using global variable - that generally is not a good idea and [should be avoided if possible](https://stackoverflow.com/q/42318053/1232087) – nam May 19 '20 at 01:31
  • Hi,@nam If the application does not running, then running it through the command line will be the first start. In addition, the judgment of `rootFrame.Content` is used to prevent repeated loading. If you have other judgment methods and processing logic (such as caching the page and then judging in `OnNavigateTo`), you can remove the judgment of `rootFrame.Content`. – Richard Zhang May 19 '20 at 01:42
  • My `OnActivated(…)` is exactly like [this one](https://stackoverflow.com/a/57232196/1232087) except that in the `//Command line activation` section there, I have added your `string commandParam = string.Empty;` line and before last line there, I have added your `if (rootFrame.Content == null){…}` block. Is there something else there that I need to change? – nam May 19 '20 at 02:37
  • Hi, In the switch statement, you need to assign value to `commandParam`, after this step is completed, you can try to run first to see if you have achieved your goal. – Richard Zhang May 19 '20 at 02:51
0

Define a variable in App.xaml.cs

sealed partial class App : Application
    {
        public string cmdLineArgs;

        public App()
        {
            this.InitializeComponent();
            this.Suspending += OnSuspending;
        }
..........
}

Then set cmdLineArgs's value in OnActivated event.

Then you can use cmdLineArgs in anywhere of your project like

string args = (Application.Current as App).cmdLineArgs;
Vincent
  • 3,124
  • 3
  • 21
  • 40