UWP: 实现 UWP 应用自启动
在上一篇文章中,我们实现了使用命令行来启动 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();
}
最后,要注意的是:如果启用了自启动,当系统启动后,应用会以最小化的方式启动。
参考资料:
Configure your app to start at log-in
UWP: 实现 UWP 应用自启动的更多相关文章
- [UWP]涨姿势UWP源码——Unit Test
之前我们讨论了涨姿势UWP的RSS数据源获取,以及作为文件存储到本地,再将数据转化成Model对象.这部分非UI的内容非常适合添加Unit Test.不涉及UI的话,UT写起来简单高效,很是值得投入一 ...
- [UWP]涨姿势UWP源码——IsolatedStorage
前一篇涨姿势UWP源码分析从数据源着手,解释了RSS feed的获取和解析,本篇则会就数据源的保存和读取进行举例. 和之前的Windows Runtime一样,UWP采用IsolatedStorage ...
- [UWP]涨姿势UWP源码——RSS feed的获取和解析
本篇开始具体分析涨姿势UWP这个APP的代码,首先从数据的源头着手,即RSS feed的获取和解析,相关的类为RssReader,所有和数据相关的操作均放在里面. 涨姿势网站提供的RSS feed地址 ...
- [UWP]涨姿势UWP源码——极简的RSS阅读器
涨姿势UWP,一个开源的RSS阅读器,一个纯粹的项目,一个有道德的APP,一个脱离了低级趣味的作者,一些有益于人民的代码.骚年,还等什么,来涨点姿势吧! 该项目代码可能会引起部分人群的不适,敏感人群请 ...
- [UWP]涨姿势UWP源码——UI布局
懒癌晚期兼正月里都是过年,一直拖到今天才继续更新.之前的几篇介绍了数据的来源,属于准备工作.本篇我们正式开始构建涨姿势UWP程序的UI界面. 我们这个Hello World程序比较简单,总共只有一个页 ...
- [UWP]涨姿势UWP源码——适配电脑和手机
上一篇我们介绍了绘制主界面的MainPage.xaml,本篇则会结合MainPage.xaml.cs来讲一讲如何适配电脑和手机这些不同尺寸的设备. 同时适配电脑和手机存在几个麻烦的地方: 屏幕尺寸差距 ...
- 张高兴的 UWP 开发笔记:应用内启动应用 (UWP Launch UWP)
需求:在 A 应用内启动 B 应用,如果 B 应用未安装则跳转应用商店搜索. 启动方式使用 Uri 启动,本文使用尽可能简单,并且能拿来直接用的代码.不涉及启动后的应用数据交互,如需深入了解,请戳 M ...
- UWP: 在 UWP 中使用 Entity Framework Core 操作 SQLite 数据库
在应用中使用 SQLite 数据库来存储数据是相当常见的.在 UWP 平台中要使用 SQLite,一般会使用 SQLite for Universal Windows Platform 和 SQLit ...
- [UWP]针对UWP程序多语言支持的总结,含RTL
UWP 对 Globalization and localization 的支持非常好,可以非常容易地实现应用程序本地化. 所谓本地化,表现最为直观的就是UI上文字和布局方式了,针对文字,提供不同的语 ...
随机推荐
- BitCoin p2p通信过程
众所周知,Bitcoin是建立在p2p网络上的,但是具体的通信过程一直没有搞懂,所以特意去bitcoin的Developer Guid上去了解了一下.由于本人英文水平有限,理解难免有偏差的地方,希望大 ...
- JS CKEditor使用setData后绑定click事件
CKEditor使用setData()时会自动丢失初始时绑定的时间,在百度时发现有很多方法都不对. 近期在做项目的时候,由于客户需要,将原来的文本格式的textarea标签更改成富文本编辑器--CKE ...
- [笔记]《JavaScript高级程序设计》- 最佳实践
一.可维护性 1 什么是可维护的代码 可理解性--其他人可以接受代码并理解它的意图和一般途径,而无需原开发人员的完整解释. 直观性--代码中的东西一看就能明白,不管其操作过程多么复杂. 可适应性--代 ...
- 记一个CRenderTarget中的BUG及解决办法
转载请注明出处:http://www.cnblogs.com/Ray1024 一.问题描述 在MFC中使用Direct2D有现成的方法,在Visual Studio 2010 SP1及以上环境中MFC ...
- vs2008中xlslib与libxls库的编译及使用
C++用来操作Excel的方法很多,但是涉及到跨平台,同时又要对Excel的读写操作兼顾,而且免费的库,那应该是要用xlslib和libxls了.由于技术比较菜,折腾这个折腾了一个星期了.最开始是使用 ...
- 80、Flask用法简析
本篇导航: 基本使用 模板.请求和响应 Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于 ...
- HTML基础知识(表格、表单)
6.表格 l 概念:表格一定具有行和列 注:使用<thead><tbody><tfoot>,使浏览器能独立于表格表头和表格页脚的表格主体滚动.当包含多个页面的表格 ...
- JavaScript闭包的深入理解
闭包算是javascript中一个比较难理解的概念,想要深入理解闭包的原理,首先需要搞清楚其他几个概念: 一.栈内存和堆内存 学过C/C++的同学可能知道,计算机系统将内存分为栈和堆两部分(大学的基础 ...
- orm查询
all:models.表名.objects.all() 结果是queryset集合 filter: models.表名.objects.filter() 结果是queryset集合 get: mode ...
- 循序渐进之Spring AOP(2) - 基本概念
学习AOP前要先了解几个重要术语:Joinpoint.Pointcut.Advice 仍然以改装车比喻,拿到心爱的汽车后想做改装,第一件事是什么?找到要改装的地方.车上可改装的地方很多,但每个人感兴趣 ...