Site icon 지락문화예술공작단

Configure your app to start at log-in

Configure your app to start at log-in

For a long time, desktop PC users have been able to configure Win32 apps to start at startup or user log-in. This has also been possible for Desktop Bridge apps since the Windows 10 Anniversary Update (v10.0.14393.0). We’ve now extended this feature to allow regular Universal Windows Apps to take part in this also. This is available in Insider builds from Build 16226 onwards, along with the corresponding SDK. In this post, we’ll look at the code changes you need to make in your manifest and in your App class to handle the startup scenario, and how your app can work with the user to respect their choices.

Here’s a sample app, called TestStartup – the app offers a button to request enabling the startup behavior, and reports current status. Typically, you’d put this kind of option into a settings page of some kind in your app.

The first thing to note is that you must use the windows.startupTask Extension in your app manifest under the Extensions node, which is a child of the Application node. This is documented here. The same Extension declaration is used for both Desktop Bridge and regular UWP apps – but there are some differences.

Desktop Bridge App UWP App

xmlns:desktop="http://schemas.microsoft.com/
appx/manifest/desktop/windows10"


xmlns:uap5="http://schemas.microsoft.com/
appx/manifest/uap/windows10/5"


<desktop:Extension
  Category="windows.startupTask"
  Executable="MyDesktopBridgeApp.exe"
  EntryPoint="Windows.FullTrustApplication">
  <desktop:StartupTask
    TaskId="MyStartupId"
    Enabled="false"
    DisplayName="Lorem Ipsum" />
</desktop:Extension>


<uap5:Extension
  Category="windows.startupTask"
  Executable="TestStartup.exe"
  EntryPoint="TestStartup.App">
  <uap5:StartupTask
    TaskId="MyStartupId"
    Enabled="false"
    DisplayName="Lorem Ipsum" />
</uap5:Extension>

For both Desktop Bridge apps and regular UWP apps, the user is always in control, and can change the Enabled state of your startup app at any time via the Startup tab in Task Manager:

Also for both app types, the app must be launched at least once before the user can change the Disabled/Enabled state. This is potentially slightly confusing: if the user doesn’t launch the app and then tries to change the state to Enabled in Task Manager, this will seem to be set. However, if they then close Task Manager and re-open it, they will see that the state is still Disabled. What’s happening here is that Task Manager is correctly persisting the user’s choice of the Enabled state – but this won’t actually allow the app to be activated at startup unless and until the app is launched at least once first – hence the reason it is reported as Disabled.

In your UWP code, you can request to be enabled for startup. To do this, use the StartupTask.GetAsync method to initialize a StartupTask object (documented here) – passing in the TaskId you specified in the manifest – and then call the RequestEnableAsync method. In the test app, we’re doing this in the Click handler for the button. The return value from the request is the new (possibly unchanged) StartupTaskState.


async private void requestButton_Click(object sender, RoutedEventArgs e)
{
    StartupTask startupTask = await StartupTask.GetAsync("MyStartupId");
    switch (startupTask.State)
    {
        case StartupTaskState.Disabled:
            // Task is disabled but can be enabled.
            StartupTaskState newState = await startupTask.RequestEnableAsync();
            Debug.WriteLine("Request to enable startup, result = {0}", newState);
            break;
        case StartupTaskState.DisabledByUser:
            // Task is disabled and user must enable it manually.
            MessageDialog dialog = new MessageDialog(
                "I know you don't want this app to run " +
                "as soon as you sign in, but if you change your mind, " +
                "you can enable this in the Startup tab in Task Manager.",
                "TestStartup");
            await dialog.ShowAsync();
            break;
        case StartupTaskState.DisabledByPolicy:
            Debug.WriteLine(
                "Startup disabled by group policy, or not supported on this device");
            break;
        case StartupTaskState.Enabled:
            Debug.WriteLine("Startup is enabled.");
            break;
    }
}

Because Desktop Bridge apps have a Win32 component, they run with a lot more power than regular UWP apps generally. They can set their StartupTask(s) to be Enabled in the manifest and do not need to call the API. For regular UWP apps, the behavior is more constrained, specifically:

Where a request triggers a user-consent prompt (UWP apps only), the message includes the DisplayName you specified in your manifest. This prompt is not shown if the state is DisabledByUser or DisabledByPolicy.

If your app is enabled for startup activation, you should handle this case in your App class by overriding the OnActivated method. Check the IActivatedEventArgs.Kind to see if it is ActivationKind.StartupTask, and if so, case the IActivatedEventArgs to a StartupTaskActivatedEventArgs. From this, you can retrieve the TaskId, should you need it. In this test app, we’re simply passing on the ActivationKind as a string to MainPage.


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

    string payload = string.Empty;
    if (args.Kind == ActivationKind.StartupTask)
    { 
        var startupArgs = args as StartupTaskActivatedEventArgs;
        payload = ActivationKind.StartupTask.ToString();
    }

    rootFrame.Navigate(typeof(MainPage), payload);
    Window.Current.Activate();
}

Then, the MainPage OnNavigatedTo override tests this incoming string and uses it to report status in the UI.


protected override void OnNavigatedTo(NavigationEventArgs e)
{
    string payload = e.Parameter as string;
    if (!string.IsNullOrEmpty(payload))
    {
        activationText.Text = payload;

        if (payload == "StartupTask")
        {
            requestButton.IsEnabled = false;
            requestResult.Text = "Enabled";
            SolidColorBrush brush = new SolidColorBrush(Colors.Gray);
            requestResult.Foreground = brush;
            requestPrompt.Foreground = brush;
        }
    }
}

Note that when your app starts at startup, it will start minimized in the taskbar. In this test app, when brought to normal window mode, the app reports the ActivationKind and StartupTaskState:

Using the windows.startupTask manifest Extension and the StartupTask.RequestEnableAsync API, your app can be configured to start at user log-in. This can be useful for apps which the user expects to use heavily, and the user has control over this – but it is still a feature that you should use carefully. You should not use the feature if you don’t reasonably expect the user to want it for your app – and you should avoid repeatedly prompting them once they’ve made their choice. The inclusion of a user-prompt puts the user firmly in control, which is an improvement over the older Win32 model.

Sample Code here.

Source: Configure your app to start at log-in

Exit mobile version