这个功能必须在“红石-1”(build 14393)以上的系统版中才能使用,运行在一台设备上的应用,可以通过URI来启动另一台设备上的应用。激活远程应用需要以下前提:
- 系统必须是build 14393或以上版本,UWP应用必须使用14393或以上版本的SDK开发。
- 被启动的应用应当支持协议激活,比如Cortana的协议URI为:【ms-cortana:】,当然如果是你自己开发的应用,可以自己定义一个协议,名字随便取,不要跟系统的协议或别人的应用冲突就行,比如:【haha:】【zxzx:】等。
- 必须用同一个Microsoft帐号登录的设备。即同一个MS帐号登录的设备才可以。这个功能得保证一定的安全性,肯定不能让你随便什么设备都能连,那应用就成了木马了。
设置种类没有限制,只要运行“红石”或以上的Windows 10系统就行,包括PC、平板、Hub、手机、xBox、笔记本、Iot、全息虚拟化设备……如果是虚拟机里面装的系统,用MS帐号登录就可以了,只要是Win 10,管你什么设备,都可以耍。
是不是很高大上,下面老周就说说怎么耍,老规矩,还是先来了解一下方法。
我们要用到两个命名空间,你要用的类,就从这两个命名空间里面找就行了,一定要学会用“对象浏览器”窗口。
- Windows.System
- Windows.System.RemoteSystems
看看名字,Remote System,你都可以猜到七分,肯定和远程调用有关的。
要调用远程设备上的应用,首先得找出这些设备,SDK提供了两种方法来实现。第一种方法比较简单,直接通过设备名来找,调用RemoteSystem.FindByHostNameAsync(HostName)静态方法,指定要查找的设备名,如果找到,就返回一个RemoteSystem实例(可异步等待)。RemoteSystem类封装了远程系统相关的信息,信息量不大,无非就是计算机名,以及一个ID值,这个ID可以用于唯一标识设备。
第二种方法工程量有点大,它是通过创建一个RemoteSystemWatcher对象,然后用这个对象来监视远程设备的连接情况,如果找到设备,会发生RemoteSystemAdded事件,如果某个设备被移除(MS帐号不再登录该设备,并在设备管理网页中移除设备)就会引发RemoteSystemRemoved事件。
要开启监视就调用Start方法,要停止就调用Stop方法。
在创建RemoteSystemWatcher对象时,可以向RemoteSystem.CreateWatcher方法传递若干个过滤器,以确定查找范围。过滤器类都会实现IRemoteSystemFilter接口。
可选的过滤器可以有这些:
- RemoteSystemKindFilter:按设备类型来过滤,如桌面、手机、xBox等,这个字符串可以从RemoteSystemKinds类的静态属性中获取。
- RemoteSystemDiscoveryTypeFilter:按发现范围来过滤,规则由RemoteSystemDiscoveryType枚举来定义,Any表示不限制范围,Proximal表示通过内网或蓝牙可以连接的范围来找,Cloud是云端记录的设备,就是用MS帐号登录的设备。当然大提前是这些设备都用MS帐号登录并使用中。
- RemoteSystemStatusTypeFilter:通过设备的当前状态来过滤,即这个设备当前是否处于可连接状态。
查找到远程设备后,使用RemoteSystem实例创建一个RemoteSystemConnectionRequest实例,因为激活应用的时候要用到。
最后把刚创建的RemoteSystemConnectionRequest实例,连同要启动应用的URI一起传递给RemoteLauncher类的LaunchUriAsync方法就可以启动远程设备上的应用了。
下面,实战一下。
这个示例不复杂,先扫描可用的远程设备(电脑、手机、平板、游戏机通杀),然后选择一个设备,最终启动目标设备上的【计算器】应用。UWP计算器的协议URI为:【calculator:】(不包括【】)。
首先,查找一下设备。
var reqres = await RemoteSystem.RequestAccessAsync(); if (reqres != RemoteSystemAccessStatus.Allowed) { btnLaunch.IsEnabled = false; return; } List<IRemoteSystemFilter> filterList = new List<IRemoteSystemFilter>(); RemoteSystemDiscoveryTypeFilter ft1 = new RemoteSystemDiscoveryTypeFilter(RemoteSystemDiscoveryType.Any); string[] kinds = { RemoteSystemKinds.Desktop, RemoteSystemKinds.Phone, RemoteSystemKinds.Xbox }; RemoteSystemKindFilter ft2 = new RemoteSystemKindFilter(kinds); filterList.Add(ft1); filterList.Add(ft2); watcher = RemoteSystem.CreateWatcher(filterList); watcher.RemoteSystemAdded += RemoteSystem_Added; watcher.RemoteSystemRemoved += RemoteSystem_Removed; watcher.Start();
注意,在做任何查找操作之前,必须先调用RequestAccessAsync方法,确定系统允许你操作才行,否则是白忙一场。
下面代码处理watcher的两个事件。
private async void RemoteSystem_Removed(RemoteSystemWatcher sender, RemoteSystemRemovedEventArgs args) { await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { RemoteSystem sys = remoteSystems.FirstOrDefault(r => r.Id == args.RemoteSystemId); if (sys != null) { remoteSystems.Remove(sys); } }); } private async void RemoteSystem_Added(RemoteSystemWatcher sender, RemoteSystemAddedEventArgs args) { await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { remoteSystems.Add(args.RemoteSystem); }); }
现在,可以在选定的设备上启动计算器了。
if (lv.SelectedIndex == -1) return; btnLaunch.IsEnabled = false; RemoteSystem rmsys = lv.SelectedItem as RemoteSystem; Uri remoteUri = new Uri("calculator:"); RemoteSystemConnectionRequest request = new RemoteSystemConnectionRequest(rmsys); var r = await RemoteLauncher.LaunchUriAsync(request, remoteUri); btnLaunch.IsEnabled = true;
还有很关键一步,就是配置清单文件,如果不配置,是没有权限的。
支持远程系统的设备功能是在版本3的XML命名空间中声明的,所以要先引入。
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
给它一个前缀叫uap3,后面方便引用。然后声明相关的Capability。
<Capabilities> <Capability Name="internetClient" /> <uap3:Capability Name="remoteSystem" /> </Capabilities>
好了,一切都准备好了,先启动另一台设备(或者虚拟机中的系统)。
然后回到开发机,运行应用,它会查找到你登录过的设备。
在列表中选择一台设备,再点下面的按钮,如果没有发生自然灾害的话,你的另一台设备上的【计算器】应用就会启动。如下图。
好了,今天的话题就讨论到这里吧。