UWP通常是没有让设备关机和重启的权限的。但是在Windows 10 IoT Core中是有办法实现的。安装Windows 10 Iot Core之后默认启动的那个欢迎页面右上角是有关机和重启按钮的。其实就是个UWP,它的源代码在:https://github.com/ms-iot/samples/tree/develop/IoTCoreDefaultApp 

分析源代码可以发现,关机和重启是通过ShutDownManager这个class实现的。

#region Assembly Windows.System.SystemManagementContract, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime
// C:\Program Files (x86)\Windows Kits\10\References\Windows.System.SystemManagementContract\2.0.0.0\Windows.System.SystemManagementContract.winmd
#endregion

using System;
using Windows.Foundation.Metadata;

namespace Windows.System
{
    [ContractVersion(typeof(SystemManagementContract), 65536)]
    [Static(typeof(IShutdownManagerStatics), 65536, "Windows.System.SystemManagementContract")]
    [Threading(ThreadingModel.Both)]
    public static class ShutdownManager
    {
        public static void BeginShutdown(ShutdownKind shutdownKind, TimeSpan timeout);
        public static void CancelShutdown();
    }
}

其中ShutdownKind的枚举类型定义如下:

#region Assembly Windows.System.SystemManagementContract, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime
// C:\Program Files (x86)\Windows Kits\10\References\Windows.System.SystemManagementContract\2.0.0.0\Windows.System.SystemManagementContract.winmd
#endregion

using Windows.Foundation.Metadata;

namespace Windows.System
{
    [ContractVersion(typeof(SystemManagementContract), 65536)]
    public enum ShutdownKind
    {
        Shutdown = 0,
        Restart = 1
    }
}

Shutdown就是关机,Restart就是重启。

然而,如果我们要在自己的IoT应用里面调用,会碰到个巨坑。首先,代码是这样的:

private void ShutdownHelper(ShutdownKind kind)
{
    ShutdownManager.BeginShutdown(kind, TimeSpan.FromSeconds(0.5));
}

private void BtnRestart_OnClick(object sender, RoutedEventArgs e)
{
    ShutdownHelper(ShutdownKind.Restart);
}

private void BtnShutdown_OnClick(object sender, RoutedEventArgs e)
{
    ShutdownHelper(ShutdownKind.Shutdown);
}

运行就会爆炸!

抛出异常:没有权限

通常在UWP里,调用没有权限的API会爆炸的解决办法是在应用的manifest文件里勾选对应的权限。然而这个关机和重启,在VS的界面里是没有选项的。我们需要用XML编辑器打开

Package.appxmanifest,然后手工加权限:

在Package节点的属性里加个命名空间

xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"

然后再Capabilities节点里加这个:

<iot:Capability Name="systemManagement" />

最后看起来就像是这样:

<?xml version="1.0" encoding="utf-8"?>
<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:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"
         IgnorableNamespaces="uap mp">
	...
  <Capabilities>
	...
    <iot:Capability Name="systemManagement" />
	...
  </Capabilities>
</Package>

现在再运行就OK了……