在上一篇文章中,我們實現了使用命令行來啟動 UWP 應用,在這一篇文章中,我們會實現 UWP 應用自啟用的實現,也即開機后或用戶登陸后,應用自己啟動。這些特性原來都是 Win32 程序所具備的,UWP 能夠支持這些特性使得它和 Win32 程序的行為進一步相同。?
實現
與實現命令行啟動一樣,實現自啟動也大體上分為兩步:首先,在 Package.appxmanifest 中添加 windows.startupTask 擴展(Extension);然后,在 App 類中處理 OnActivated 事件。事實上,除了這兩步外,我們還需要增加檢查 StartupTask 的狀態并允許用戶控制自啟動的邏輯。
1. 修改 Package.appxmanifest?
右擊項目中的 Package.appxmanifest 文件,在快捷菜單中選擇“打開方式“->”XML 文本編輯器“。打開后,對它的內容按以下修改:
<Packagexmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"IgnorableNamespaces="uap mp uap5">...<Applications><Application ... <Extensions><uap5:Extension Category="windows.startupTask" EntryPoint="AppAutoRun.App" Executable="AppAutoRun.exe"><uap5:StartupTask DisplayName="AppAutoRun" Enabled="true" TaskId="AppAutoRun"/></uap5:Extension></Extensions> </Application></Applications> </Package>
上述加粗的部分就是添加的擴展 windows.startupTask,其 EntryPoint 和 Executable 屬性分別指明 App 類的完整名稱以及當前應用的 exe 名稱。
在 Extension 節點中,添加了一個節點 StartupTask,它有三個屬性,說明如下:
- TaskId:任務Id,必填,在所有的 UWP 應用中,它必須是唯一的,不能和其它應用的 TaskId 相同;
- Enabled:是否啟用,必填,指明是否啟用當前應用為自啟動行為;
- DisplayName:顯示名稱,可選,在“任務管理器”中“啟動”選項卡中的顯示名稱;
需要說明的是,Enabled 屬性應該設置為 false;事實上這個屬性會被忽略;因為 UWP 要實現自啟動,至少需要啟動一次,并且向用戶請求同意才行。另外目前只能添加一個 StartupTask 節點。
此時,可以將應用部署(Deploy)到本機上,然后,在“任務管理器”中“啟動”選項卡上,我們就可以看到了。
這里,右擊每個任務,可以對它的狀態進行控制(啟用/禁用),可以看到當前應用的狀態是“已禁用”。注意,在設置它的狀態之前,App 需要至少被啟動過一次。否則這里的設置是不起作用的。
?2. 查看并更改任務狀態
除了在 Package.appxmanifest 中增加擴展外,我們還需要使用相關的 API 來查看所添加的 StartupTask 的狀態,以及對它的更改。在 MainPage.xaml 中增加以下代碼:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"><Grid Margin="12"><StackPanel><TextBlock x:Name="tbState" /><Buttonx:Name="btnSetState"Margin="0,4,0,0"Click="btnSetState_Click" /></StackPanel></Grid></Grid>
在 MainPage.xaml.cs 中增加以下代碼:
private async void MainPage_Loaded(object sender, RoutedEventArgs e){await LoadState();}public async Task LoadState(){var task = await StartupTask.GetAsync("AppAutoRun");this.tbState.Text = $"Status: {task.State}";switch (task.State){case StartupTaskState.Disabled:// 禁用狀態this.btnSetState.Content = "啟用";this.btnSetState.IsEnabled = true;break;case StartupTaskState.DisabledByPolicy:// 由管理員或組策略禁用this.btnSetState.Content = "被系統策略禁用";this.btnSetState.IsEnabled = false;break;case StartupTaskState.DisabledByUser:// 由用戶手工禁用this.btnSetState.Content = "被用戶禁用";this.btnSetState.IsEnabled = false;break;case StartupTaskState.Enabled:// 當前狀態為已啟用this.btnSetState.Content = "已啟用";this.btnSetState.IsEnabled = false;break;}}private async void btnSetState_Click(object sender, RoutedEventArgs e){var task = await StartupTask.GetAsync("AppAutoRun");if (task.State == StartupTaskState.Disabled){await task.RequestEnableAsync();}// 重新加載狀態await LoadState();}
我們通過 StartupTask 類(位于 Windows.ApplicationModel 命名空間下)的 GetAsync 來獲取指定 TaskId 的自啟動任務(StartupTask)。StartupTask 類具有一個 State 的枚舉屬性,用于表示其狀態。它們的值及其意義,在注釋中已經說明。
補充說明以下幾點:
- 最開始時,任務的 State 是 Disabled;
- 唯有當其 State 是 Disabled 時,才能以編程的方式使用啟動;
- 當其 State 是 DisabledByUser 或 DisabledByPolicy,需要經由用戶手工啟動;
- 不支持以編程的方式使其 State 成為 Disabled;
通過 StartupTask 類的 RequestEnableAsync 方法,可以向用戶請求將其啟動,調用這個方法后,會彈出如下窗口:
當用戶選擇“啟用”后,下次系統啟動后它就會自動啟動,反之,如果選擇”禁用“,那么它的狀態會是 DisabledByUser。要想啟用它,就需要打開”任務管理器“,在”啟動“選項卡上右擊它,選擇“啟用”。
3. 處理 OnActivated 事件
然后,在 App 類的 OnActivated 事件上增加對 ActivationKind 類的判斷,并作相應的處理即可。代碼如下:
protected override void OnActivated(IActivatedEventArgs args){Frame rootFrame = Window.Current.Content as Frame;if (rootFrame == null){rootFrame = new Frame();Window.Current.Content = rootFrame;}if (args.Kind == ActivationKind.StartupTask){var startupArgs = args as StartupTaskActivatedEventArgs;}rootFrame.Navigate(typeof(MainPage), args.Kind);Window.Current.Activate();}
最后,要注意的是:如果啟用了自啟動,當系統啟動后,應用會以最小化的方式啟動。?
參考資料:
Configure your app to start at log-in