Настройте UWP приложение для запуска при входе в систему

В течение долгого времени пользователи настольных ПК смогли настроить приложения Win32 для автозагрузки при запуске системы или входе пользователя в систему. Это также стало возможным для приложений Desktop Bridge с момента выхода обновления Windows 10 (v10.0.14393.0). Теперь мы расширили эту функцию, чтобы обычные универсальные приложения Windows  (UWP) также получили такую возможность. Это доступно в сборках Insider начиная с  Build 16226 и вместе с соответствующим SDK. В этом посте мы рассмотрим изменения кода, которые необходимо внести в манифест и в класс App для обработки сценария автозагрузки, и то, как ваше приложение может работать с пользователем.

Вот пример приложения, которое мы назвали TestStartup — приложение предлагает нажать кнопку для запроса включения режима автозагрузки приложения при запуске системы и сообщает текущий статус. Как правило, этот вариант можно поместить на страницу настроек в приложении.

Прежде всего следует отметить, что вы должны использовать расширение windows.startupTask в манифесте приложения в узле «Расширения», который является дочерним узлом узла «Приложение». Это описано здесь. Такая же декларация расширения используется как для приложений Desktop Bridge, так и для обычных приложений UWP, но есть некоторые отличия.
— Desktop Bridge доступен только на настольном компьютере, поэтому он использует пространство имен XML для конкретного рабочего стола. Новая реализация UWP предназначена для использования, как правило, в UWP, поэтому использует общее пространство имен UAP (контрактная версия 5) — хотя это и понятно, в настоящее время он по-прежнему доступен только для десктопных приложений.
— Desktop Bridge EntryPoint должен быть «Windows.FullTrustApplication», тогда как для обычного UWP это полное имя пространства имен вашего класса App.
— Приложения Desktop Bridge могут установить для атрибута Enabled значение true, а это означает, что приложение произведет автозагрузку при запуске системы без необходимости вручную включить его. И наоборот, для обычных приложений UWP этот атрибут игнорируется, и значение неявно устанавливается на «отключена». Вместо этого пользователь должен сначала запустить приложение, и приложение должно запросить его активировать автозагрузку с запуском системы.
— Для приложений Desktop Bridge разрешено несколько расширений StartupTask, каждый из которых может использовать другой исполняемый файл. И наоборот, для обычных приложений UWP у вас будет только одно исполняемое расширение и одно расширение для StartupTask.

Desktop Bridge App:

  1. xmlns:desktop=»http://schemas.microsoft.com/
  2. appx/manifest/desktop/windows10″

 

  1. <desktop:Extension
  2. Category=«windows.startupTask»
  3. Executable=«MyDesktopBridgeApp.exe»
  4. EntryPoint=«Windows.FullTrustApplication»>
  5. <desktop:StartupTask
  6. TaskId=«MyStartupId»
  7. Enabled=«false»
  8. DisplayName=«Lorem Ipsum» />
  9. </desktop:Extension>

UWP App:

  1. xmlns:uap5=»http://schemas.microsoft.com/
  2. appx/manifest/uap/windows10/5″

  1. <uap5:Extension
  2. Category=«windows.startupTask»
  3. Executable=«TestStartup.exe»
  4. EntryPoint=«TestStartup.App»>
  5. <uap5:StartupTask
  6. TaskId=«MyStartupId»
  7. Enabled=«false»
  8. DisplayName=«Lorem Ipsum» />
  9. </uap5:Extension>

Для приложений Desktop Bridge и обычных приложений UWP пользователь всегда имеет контроль над ситуацией и может в любое время изменить состояние включенного приложения для автозагрузки с помощью вкладки «Автозагрузка» в Диспетчере задач:

Также для обоих типов приложений приложение должно запускаться по крайней мере один раз, прежде чем пользователь сможет изменить состояние «отключено/включено». Это потенциально несколько запутанно: Также для обоих типов приложений, приложение должно быть запущено по крайней мере один раз, прежде чем пользователь может изменить состояние Отключено/включено. Это потенциально немного запутанно: если пользователь не запускает приложение, а затем пытается изменить состояние на Enabled в диспетчере задач, кажется, что состояние будет установлено. Однако, если он затем закроет диспетчер задач и снова откроет его, он увидят, что состояние по-прежнему Disabled. Суть происходящего здесь заключается в том, что диспетчер задач правильно сохраненяет выбор пользователя для включенного состояния, но это не будет на самом деле позволять приложению быть активированным при запуске до тех пор, пока приложение не запустится по крайней мере один раз, следовательно по этой причине будет сообщено, что состояние Disabled.
В коде UWP вы можете запросить включение для автозагрузки. Для этого используйте метод StartupTask.GetAsync для инициализации объекта StartupTask (задокументированный здесь) — передачи в TaskId, указанного вами в манифесте, — и затем вызовите метод RequestEnableAsync. В тестовом приложении мы делаем это в обработчике Click для кнопки. Возвращаемое значение запроса — это новый (возможно, неизменный) StartupTaskState.

  1. async private void requestButton_Click(object sender, RoutedEventArgs e)
  2. {
  3. StartupTask startupTask = await StartupTask.GetAsync(«MyStartupId»);
  4. switch (startupTask.State)
  5. {
  6. case StartupTaskState.Disabled:
  7. // Task is disabled but can be enabled.
  8. StartupTaskState newState = await startupTask.RequestEnableAsync();
  9. Debug.WriteLine(«Request to enable startup, result = {0}», newState);
  10. break;
  11. case StartupTaskState.DisabledByUser:
  12. // Task is disabled and user must enable it manually.
  13. MessageDialog dialog = new MessageDialog(
  14. «I know you don’t want this app to run « +
  15. «as soon as you sign in, but if you change your mind, « +
  16. «you can enable this in the Startup tab in Task Manager.»,
  17. «TestStartup»);
  18. await dialog.ShowAsync();
  19. break;
  20. case StartupTaskState.DisabledByPolicy:
  21. Debug.WriteLine(
  22. «Startup disabled by group policy, or not supported on this device»);
  23. break;
  24. case StartupTaskState.Enabled:
  25. Debug.WriteLine(«Startup is enabled.»);
  26. break;
  27. }
  28. }

Поскольку приложения Desktop Bridge имеют компонент Win32, они работают с гораздо большими возможностями, чем обычные приложения UWP. Они могут установить свои StartupTask в состояние Enabled в манифесте и не нужно вызывать API. Для обычных UWP приложений поведение более ограничено, в частности:
— По умолчанию используется значение Disabled, поэтому в обычном случае пользователь должен запускать приложение хотя бы один раз явно — это дает приложению возможность запросить включение.
— Когда приложение вызывает RequestEnableAsync, появится диалоговое окно пользовательского приглашения для UWP приложений (или если вы вызовете из компонента UWP в приложении Desktop Bridge из Windows 10 Fall Creators Update).
— StartupTask включает метод Disable. Если состояние Enabled, приложение может использовать API, чтобы установить его на Disabled. Если приложение затем запросит снова включить, это также вызовет приглашение пользователя.
— Если пользователь отключает (либо через подсказку пользователя, либо через вкладку Автозагрузка в Диспетчере задач), то приглашение снова не отображается, независимо от каких-либо запросов приложения. Приложение может, конечно, иметь свои собственные пользовательские подсказки, попросив пользователя внести вручную изменения в Диспетчер задач, но если пользователь явно отключил ваш запуск, вы должны, вероятно, уважать его решение и прекратить их предлагать. В приведенном выше примере кода приложение реагирует на DisabledByUser, открывая свой собственный диалог сообщений — вы можете сделать это, если хотите, но следует подчеркнуть, что существует риск, что вы просто раздражаете пользователя.
— Если функция отключена локальной политикой администратора или группы, то приглашение пользователя не отображается, а запуск не может быть активирован. Существующее перечисление StartupTaskState было расширено с новым значением DisabledByPolicy. Когда приложение увидит DisabledByPolicy, ему следует избегать повторного запроса, чтобы их задача была включена, потому что запрос никогда не будет одобрен до тех пор, пока политика не изменится.
— Платформы, отличные от десктопной, которые не поддерживают задачи автозагрузки, также сообщают о состоянии DisabledByPolicy.

Если запрос инициирует приглашение пользователя (только для приложений UWP), сообщение включает DisplayName, указанное в вашем манифесте. Это приглашение не отображается, если состояние DisabledByUser или DisabledByPolicy.

Если ваше приложение включено для активации при запуске, вы должны обработать этот случай в своем классе App, переопределив метод OnActivated. Проверьте IActivatedEventArgs.Kind, чтобы узнать, является ли это ActivationKind.StartupTask, и если да, укажите IActivatedEventArgs в StartupTaskActivatedEventArgs. Из этого вы можете получить TaskId, если вам это нужно. В этом тестовом приложении мы просто передаем ActivationKind как строку MainPage.

  1. protected override void OnActivated(IActivatedEventArgs args)
  2. {
  3. Frame rootFrame = Window.Current.Content as Frame;
  4. if (rootFrame == null)
  5. {
  6. rootFrame = new Frame();
  7. Window.Current.Content = rootFrame;
  8. }
  9. string payload = string.Empty;
  10. if (args.Kind == ActivationKind.StartupTask)
  11. {
  12. var startupArgs = args as StartupTaskActivatedEventArgs;
  13. payload = ActivationKind.StartupTask.ToString();
  14. }
  15. rootFrame.Navigate(typeof(MainPage), payload);
  16. Window.Current.Activate();
  17. }

Затем MainPage OnNavigatedTo переопределить тесты приходящей строки и использует их для отчета о состоянии в пользовательском интерфейсе.

  1. protected override void OnNavigatedTo(NavigationEventArgs e)
  2. {
  3. string payload = e.Parameter as string;
  4. if (!string.IsNullOrEmpty(payload))
  5. {
  6. activationText.Text = payload;
  7. if (payload == «StartupTask»)
  8. {
  9. requestButton.IsEnabled = false;
  10. requestResult.Text = «Enabled»;
  11. SolidColorBrush brush = new SolidColorBrush(Colors.Gray);
  12. requestResult.Foreground = brush;
  13. requestPrompt.Foreground = brush;
  14. }
  15. }
  16. }

Обратите внимание, что когда ваше приложение производит автозагрузку при запуске, оно запускается на панели задач в минимальном состоянии. В этом тестовом приложении, когда его приводят в нормальный оконный режим, приложение сообщает ActivationKind и StartupTaskState:

Используя средство расширения windows.startupTask API StartupTask.RequestEnableAsync, ваше приложение может быть настроено для автозагрузки при входе пользователя в систему. Это может быть полезно для приложений, которые пользователь ожидает использовать в значительной степени регулярно, и у пользователя есть контроль над этим — но это все еще функция, которую вы должны использовать осторожно. Вы не должны использовать эту функцию, если вы не ожидаете, что пользователь захочет ее использовать для вашего приложения, и вам следует избегать многократного запроса после того, как они сделали свой выбор. Включение пользовательского запроса позволяет пользователю жестко контролировать, что является улучшением по сравнению с более старой моделью Win32.

Пример кода здесь.

Перевод оригинальной публикации Configure your app to start at log-in
Автор: Andrew Whitechapel / Senior Program Manager, Windows
Перевод: Сергей Урусов

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *