用于分配的访问权限的展台应用:最佳做法

在 Windows 10 中,你可以使用分配的访问权限来创建展台设备,使用户能够仅与单个通用 Windows 应用进行交互。 本文介绍如何实现展台应用和最佳做法。

分配的访问权限提供两种不同的体验:

  1. 单应用展台体验

    向帐户分配一个应用。 当用户登录时,他们只能访问此应用,并且系统上没有其他权限。 在此期间,展台设备处于锁定状态,展台应用在锁屏界面上方运行。 此体验通常用于面向公众的展台计算机。 有关详细信息,请参阅在Windows 10 专业版、企业或教育版上设置展台。

  2. 多应用展台体验(在 Windows 10 版本 1709 及更高版本中提供)

    可以将一个或多个应用分配给帐户。 当用户登录时,设备将在受限的 shell 体验中启动,仅访问所选应用。 有关详细信息,请参阅 创建运行多个应用的 Windows 10 展台。

本文仅介绍单应用展台体验。 在多应用体验中,所选应用在常规桌面上下文中运行,无需特殊处理或修改。

术语

术语 说明
分配的访问权限 允许系统管理员通过限制向设备用户公开的应用程序入口点来管理用户体验的功能。 例如,你可以限制企业中的客户使用一个应用,以便你的电脑像展台一样。 每当有人使用指定的帐户登录时,他们只能使用该一个应用。 他们无法使用触摸手势、鼠标、键盘或硬件按钮切换应用或关闭应用。 它们也不会看到任何应用通知。
锁屏应用(或锁定应用) 一个应用程序,既可以利用设置动态墙纸的功能,也可以利用新的锁扩展性框架。
锁屏界面应用上方(或锁定应用以上) 锁屏应用运行时在锁屏界面上方启动的应用程序(例如,桌面锁定时)。
在锁定应用下 在解锁的 Windows 上下文中正常运行的应用程序。
LockApplicationHost 一个 WinRT 类,允许上面的锁屏应用请求设备解锁,并允许应用在设备开始解锁时注册通知。
视图或应用程序视图 每个视图都是应用中的单独窗口。 应用可以具有主视图,并按需创建多个和辅助视图。 有关详细信息,请参阅 ApplicationView

windows.aboveLockScreen 扩展

Windows 10 中分配的访问权限使用锁定框架。 分配的访问权限用户登录时,后台任务会锁定桌面并启动锁上方的展台应用。 应用的行为可能会有所不同,具体取决于它是否使用 windows.aboveLockScreen 扩展。

使用 windows.aboveLockScreen ,展台应用可以访问 LockApplicationHost 运行时类,这使应用能够知道它何时在锁上方运行(因此作为展台体验运行)。 如果无法返回实例,则应用在常规桌面上下文中运行。

当锁定框架启动锁上方的展台应用并且应用具有 windows.aboveLockScreen 扩展时,锁定框架会自动在锁上方创建新的辅助视图。 主视图位于锁下。 此辅助视图包含应用的内容以及用户看到的内容。 此附加视图可用于扩展来定制展台体验。 例如,您可以:

如果应用没有 windows.aboveLockScreen 扩展,则不会创建辅助视图,并且应用会启动,就好像它正常运行一样。 此外,由于应用无法访问 LockApplicationHost 实例,因此无法确定它是否在常规上下文中运行,或者是否在展台体验中运行。 不包括扩展具有优势,例如能够支持 多个监视器

无论应用是否使用扩展,请务必保护其数据。 有关详细信息,请参阅分配的访问应用的指南。

从 Windows 10 版本 1607 开始,通用 Windows 平台(UWP)扩展不再存在限制,因此当用户配置分配的访问权限时,大多数应用都可以显示在设置中。

最佳做法

本部分适用于使用 windows.aboveLockScreen 扩展的展台应用程序。

保护信息

如果展台应用既要在分配的访问权限中运行上述锁,又要在解锁的 Windows 上下文中运行,则可能需要创建另一个页面来呈现锁定上方的锁,另一个页面用于锁定下。 这样就可以避免在展台模式下显示敏感信息,因为展台模式通常意味着匿名访问。 下面是使用两个不同的页面的步骤,一个用于锁下,另一个用于锁上方:

  1. 在 App.xaml.cs OnLaunched 函数的重写中,尝试在 rootFrame 导航之前获取 LockApplicationHost 类的实例。

  2. 如果调用失败,展台应用应在锁定下正常启动。

  3. 如果调用成功,展台应用应启动在分配的访问模式下运行的锁上方。 你可能希望此版本的展台应用具有不同的主页来隐藏敏感信息。

下面的示例演示如何执行此操作。 AssignedAccessPage.xaml 是预定义的,应用在检测到在锁定模式上方运行后导航到 AssignedAccessPage.xaml。 因此,普通页面仅在锁定方案中显示。

可以使用此方法来确定应用是否在应用生命周期中随时在锁屏界面上运行,并做出相应的反应。

using Windows.ApplicationModel.LockScreen;

// inside the override OnLaunched function in App.xaml.cs

if (rootFrame.Content == null)
{
    LockApplicationHost host = LockApplicationHost.GetForCurrentView();
    if (host == null)
    {
        // if call to LockApplicationHost is null, this app is running under lock
        // render MainPage normally
        rootFrame.Navigate(typeof(MainPage), e.Arguments);
    }
    else
    {
        // If LockApplicationHost was successfully obtained
        // this app is running as a lock screen app, or above lock screen app
        // render a different page for assigned access use
        // to avoid showing regular main page to keep secure information safe
        rootFrame.Navigate(typeof(AssignedAccessPage), e.Arguments);
    }
}

多个视图、窗口和线程

从 Windows 10 版本 1803 开始,没有 windows.aboveLockScreen 扩展的应用的展台体验支持多个视图。 若要使用多个视图,请确保展台设备的 “多显示 ”选项设置为“ 扩展这些显示器”。

当在展台体验期间启动具有多个视图(且没有 windows.aboveLockScreen)的应用时,应用的主要视图将在第一个监视器上呈现。 如果使用 CreateNewView()由应用创建新视图,则会在第二个监视器上呈现该视图。 如果应用创建另一个视图,它将转到第三个监视器,依此显示。

重要

展台设备只能显示每个监视器的一个视图。 例如,如果展台设备只有一个监视器,它将始终显示展台应用的主视图。 不会显示应用创建的新视图。

当展台应用具有 windows.aboveLockScreen 扩展并且运行在锁上方时,会以不同的方式初始化它。 其主视图位于锁下,其上方有一个辅助视图。 此辅助视图是用户看到的内容。 即使未显式创建新视图,应用实例中仍会有两个视图。

应用在锁定模式下运行时视图的 z 顺序。

可以在应用的主窗口中运行以下代码(在分配的访问模式下),以查看视图计数以及当前屏幕是否为主视图。

using Windows.ApplicationModel.Core;

CoreApplication.GetCurrentView().IsMain //false
CoreApplication.Views.Count //2

Dispatcher

每个视图或窗口都有自己的调度程序。 由于主视图对用户隐藏,因此使用 GetCurrentView() 访问在锁上运行的应用的辅助视图,而不是 MainView()。

using Windows.ApplicationModel.Core;

private async void Button_Click(object sender, RoutedEventArgs e)
{
    button.IsEnabled = false;

    // start a background task and update UI periodically (every 1 second)
    // using MainView dispatcher in below code will end up with app crash
    // in assigned access mode, use GetCurrentView().Dispatcher instead
    await CoreApplication.GetCurrentView().Dispatcher.RunAsync(
        CoreDispatcherPriority.Normal,
        async () =>
        {
            for (int i = 0; i < 60; ++i)
            {
                // do some background work, here we use Task.Delay to sleep
                await Task.Delay(1000);
                // update UI
                textBlock1.Text = "   " + i.ToString();
            }
            button.IsEnabled = true;
        });
}

当应用具有 windows.aboveLockScreen 并作为展台体验运行时,创建新视图将导致应用中出现异常:

Windows.ApplicationModel.Core.CoreApplication.CreateNewView(); //causes exception

因此,不能在多个监视器上运行多个视图。 如果你的应用需要支持其中一个,则需要从应用中删除 windows.aboveLockScreen 扩展。

添加分配访问权限的出路

在某些情况下,电源按钮、转义按钮或其他用于停止应用程序的按钮可能无法在键盘上启用或可用。 在这些情况下,提供一种方法来停止分配的访问权限,例如软件密钥。 以下事件处理程序演示如何通过响应可由软件密钥触发的按钮选择事件来停止分配的访问模式。

LockApplicationHost^ lockHost = LockApplicationHost::GetForCurrentView();
    if (lockHost != nullptr)
    {
        lockHost->RequestUnlock();
    }

生命周期管理

展台应用的生命周期由分配的访问框架处理。 如果应用意外结束,框架将尝试重新启动它。 但是,如果用户按 Ctrl+Alt+Del 打开登录屏幕,则会触发解锁事件。 分配的访问框架侦听事件,并尝试终止应用。

展台应用还可以注册此事件的处理程序,并在退出之前执行操作。 保存任何数据就是一个示例。 有关注册处理程序的示例,请参阅下面的代码。

using Windows.ApplicationModel.LockScreen;

public AssignedAccessPage()
{
    this.InitializeComponent();

    LockApplicationHost lockHost = LockApplicationHost.GetForCurrentView();
    if (lockHost != null)
    {
        lockHost.Unlocking += LockHost_Unlocking;
}
}

private void LockHost_Unlocking(LockApplicationHost sender, LockScreenUnlockingEventArgs args)
{
    // save any unsaved work and gracefully exit the app
    App.Current.Exit();
}

用户按 Ctrl+Alt+Del 并显示登录屏幕后,可能会出现两种情况:

  1. 用户知道分配的访问帐户密码并解锁桌面。 分配的访问框架启动、锁定桌面和锁屏应用启动,进而启动展台应用。

  2. 用户不知道密码或不采取任何进一步操作。 登录屏幕超时和桌面重新锁定;锁屏应用启动,进而启动展台应用。

不要在分配的访问模式下创建新的窗口或视图

如果以分配的访问模式调用该函数,则以下函数调用最终会引发运行时异常。 如果同一应用在锁定下使用,则调用该函数不会引发运行时异常。 最好使用 LockApplicationHost 来确定应用的分配访问模式,并相应地对应用进行编码,例如,如果应用处于分配的访问模式,则不会创建新视图。

Windows.ApplicationModel.Core.CoreApplication.CreateNewView(); //causes exception

附录 1:UWP 扩展

以下示例应用程序清单使用 windows.aboveLockScreenUWP 扩展。

从 Windows 10 版本 1607 开始,通用 Windows 平台(UWP)扩展不再存在限制,因此当用户配置分配的访问权限时,大多数应用都可以显示在设置中。

<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" IgnorableNamespaces="uap mp">
  <Identity Name="bd4df68b-dc18-4748-a14e-bc21dac13736" Publisher="Contoso" Version="1.0.0.0" />
  <mp:PhoneIdentity PhoneProductId="bd4df68b-dc18-4748-a14e-bc21dac13736" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
  <Properties>
    <DisplayName>AboveLock</DisplayName>
    <PublisherDisplayName>Contoso</PublisherDisplayName>
    <Logo>Assets\StoreLogo.png</Logo>
  </Properties>
  <Dependencies>
    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
  </Dependencies>
  <Resources>
    <Resource Language="x-generate" />
  </Resources>
  <Applications>
    <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="AboveLock.App">
      <uap:VisualElements DisplayName="AboveLock" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="AboveLock" BackgroundColor="transparent">
        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png">
        </uap:DefaultTile>
        <uap:SplashScreen Image="Assets\SplashScreen.png" />
      </uap:VisualElements>
      <Extensions>
        <uap:Extension Category="windows.lockScreenCall" />
        <uap:Extension Category="windows.aboveLockScreen" />
      </Extensions>
    </Application>
  </Applications>
  <Capabilities>
    <Capability Name="internetClient" />
  </Capabilities>
</Package>

附录 2:故障排除

通常情况下,如果展台应用无法在锁屏应用上方激活,可以在锁定屏幕中找到激活错误代码。 使用错误代码通过查找 Windows 系统错误代码来发现问题。 此外,事件查看器还包含有关激活失败的详细信息。 为此,请执行以下操作:

  1. 打开“事件查看器”。 有两个可能的位置可以查找激活错误。

  2. “事件查看器(本地)”窗格中,展开“Windows 日志”,然后选择“应用程序”。

  3. 此外,在事件查看器(本地)中,依次展开应用程序和服务日志Windows应用Microsoft-Windows-TWinUI/Operational

由于具有已分配访问权限的展台应用不会在全屏模式下运行, 因此 ApplicationView.GetForCurrentView()。IsFullScreenMode 返回 false。

分配的访问权限

显示应用的多个视图