在上一篇文章中,我們實現了使用命令行來啟動 UWP 應用,在這一篇文章中,我們會實現 UWP 應用自啟用的實現,也即開機後或用戶登陸後,應用自己啟動。這些特性原來都是 Win32 程式所具備的,UWP 能夠支持這些特性使得它和 Win32 程式的行為進一步相同。 實現 與實現命令行啟動一樣,實現自啟 ...
在上一篇文章中,我們實現了使用命令行來啟動 UWP 應用,在這一篇文章中,我們會實現 UWP 應用自啟用的實現,也即開機後或用戶登陸後,應用自己啟動。這些特性原來都是 Win32 程式所具備的,UWP 能夠支持這些特性使得它和 Win32 程式的行為進一步相同。
實現
與實現命令行啟動一樣,實現自啟動也大體上分為兩步:首先,在 Package.appxmanifest 中添加 windows.startupTask 擴展(Extension);然後,在 App 類中處理 OnActivated 事件。事實上,除了這兩步外,我們還需要增加檢查 StartupTask 的狀態並允許用戶控制自啟動的邏輯。
1. 修改 Package.appxmanifest
右擊項目中的 Package.appxmanifest 文件,在快捷菜單中選擇“打開方式“->”XML 文本編輯器“。打開後,對它的內容按以下修改:
<Package xmlns="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" /> <Button x: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(); }
最後,要註意的是:如果啟用了自啟動,當系統啟動後,應用會以最小化的方式啟動。