枚举设备

Windows.Devices.Enumeration API 允许你查找内部连接到系统、外部连接或可通过无线或网络协议检测到的设备。

示例

枚举所有可用设备的最简单方法是使用 FindAllAsync 命令拍摄快照(下面一节对此进行了进一步介绍)。

async void enumerateSnapshot(){
  DeviceInformationCollection collection = await DeviceInformation.FindAllAsync();
}

有关 Windows.Devices.Enumeration API 的更高级示例,请参阅设备枚举和配对示例。

枚举 API

Windows.Devices.Enumeration 命名空间使你能够查找在内部连接到系统、外部连接或可通过无线或网络协议检测到的设备。 这些 API 支持的一些功能包括:

  • 查找要连接到应用程序的设备。
  • 获取有关系统连接到或可发现的设备的信息。
  • 添加设备、连接、断开连接、更改联机状态或更改其他属性时,让应用接收通知。
  • 当设备连接、断开连接、更改联机状态或更改其他属性时,让应用接收后台触发器。

这些 API 可以通过以下任一协议和总线枚举设备,前提是单个设备和运行应用的系统支持该技术。 这不是详尽列表,特定设备可能支持其他协议。

在许多情况下,无需担心使用枚举 API。 这是因为许多使用设备的 API 将自动选择适当的默认设备或提供更简化的枚举 API。 例如, MediaElement 将自动使用默认音频呈现器设备。 只要应用可以使用默认设备,就无需在应用程序中使用枚举 API。 枚举 API 提供了一种常规和灵活的方法来发现和连接到可用设备。 本主题提供有关枚举设备的信息,并介绍了枚举设备的四种常见方法。

  • 使用 DevicePicker UI
  • 枚举系统当前可发现的设备的快照
  • 枚举当前可发现的设备并监视更改
  • 枚举当前可发现的设备并监视后台任务中的更改

DeviceInformation 对象

使用枚举 API 时,通常需要使用 DeviceInformation 对象。 这些对象包含有关设备的大多数可用信息。 下表介绍了你感兴趣的一些 DeviceInformation 属性。 有关完整列表,请参阅 DeviceInformation参考页。

properties 评论
DeviceInformation.Id 这是设备的唯一标识符,作为字符串变量提供。 在大多数情况下,这是一个不透明的值,只需从一个方法传递到另一个方法来指示你感兴趣的特定设备。 关闭应用并重新打开应用后,还可以使用此属性和 DeviceInformation.Kind 属性。 这将确保可以恢复并重复使用同一 DeviceInformation 对象。
DeviceInformation.Kind 这表示 DeviceInformation 对象表示的设备对象类型。 这不是设备类别或设备类型。 单个设备可以由多种不同类型的 DeviceInformation 对象表示。 此属性的可能值在 DeviceInformationKind列出,以及它们彼此之间的关系。
DeviceInformation.Properties 此属性包包含为 DeviceInformation 对象请求的信息。 最常见的属性很容易被引用为 DeviceInformation 对象的属性,例如使用 DeviceInformation.Name 有关详细信息,请参阅 设备信息属性

 

DevicePicker 用户界面

DevicePicker 是 Windows 提供的控件,它创建一个小 UI,使用户能够从列表中选择设备。 可以通过多种方式对其进行自定义,例如:

  • 通过将 SupportedDeviceSelectorsSupportedDeviceClasses 或两者添加到 DevicePicker.Filter 来控制 UI 中显示的设备。 在大多数情况下,只需添加一个选择器或类,但如果确实需要多个,则可以添加多个。 如果确实添加多个选择器或类,则会使用 OR 逻辑函数连接它们。
  • 指定要为设备检索的属性。 可以通过向 DevicePicker.RequestedProperties 添加属性来执行此操作。
  • 使用外观更改 DevicePicker 的外观。
  • 指定显示 DevicePicker 的大小和位置

显示 DevicePicker 时,如果添加、删除或更新设备,UI 的内容将自动更新。

请注意,不能使用 DevicePicker 指定 DeviceInformationKind。 如果想要具有特定 DeviceInformationKind 的设备,则需要生成 DeviceWatcher 并提供自己的 UI。

 

如果想要使用媒体内容,并且 DIAL 还提供自己的选取器。 它们分别是 CastingDevicePickerDialDevicePicker

枚举设备的快照

在某些情况下, DevicePicker 不适合你的需求,你需要更灵活的内容。 你可能想要生成自己的 UI,或者需要枚举设备,而无需向用户显示 UI。 在这些情况下,可以枚举设备的快照。 这涉及到查看当前连接到或与系统配对的设备。 但是,需要注意,此方法只查看可用的设备的快照,因此在枚举列表后无法找到连接的设备。 如果设备已更新或删除,你也不会收到通知。 另一个需要注意的缺点是,此方法将保留所有结果,直到整个枚举完成。 因此,当你对 AssociationEndpoint、AssociationEndpointContainerAssociationEndpointService 对象感兴趣时,不应使用此方法,因为它们通过网络或无线协议找到。 最长可能需要 30 秒才能完成。 在这种情况下,应使用 DeviceWatcher 对象枚举可能的设备。

若要枚举设备快照,请使用 FindAllAsync 方法。 此方法等待整个枚举过程完成,并将所有结果作为一个 DeviceInformationCollection 对象返回。 此方法还会重载,以便为你提供多个选项,用于筛选结果并将其限制为你感兴趣的设备。 为此, 可以提供 DeviceClass 或传入设备选择器。 设备选择器是一个高级查询语法(AQS)字符串,用于指定要枚举的设备。 有关详细信息,请参阅 生成设备选择器

除了限制结果之外,还可以指定要为设备检索的属性。 如果这样做,指定的属性将出现在集合中返回的每个 DeviceInformation 对象的属性包中。 请务必注意,并非所有属性都可用于所有设备类型。 若要查看哪些属性可用于哪些设备类型,请参阅 设备信息属性

枚举和监视设备

枚举设备的更强大且更灵活的方法是创建 DeviceWatcher。 在枚举设备时,此选项提供最大的灵活性。 它允许枚举当前存在的设备,并在添加、删除或属性更改与设备选择器匹配的设备时接收通知。 创建 DeviceWatcher 时,提供设备选择器。 有关设备选择器的详细信息,请参阅 生成设备选择器。 创建观察程序后,你将收到与提供的条件匹配的任何设备的以下通知。

  • 添加新设备时添加通知。
  • 更改你感兴趣的属性时更新通知。
  • 当设备不再可用或不再与筛选器匹配时删除通知。

在大多数情况下,使用 DeviceWatcher 时,会维护设备列表并向其添加、从中删除项或更新项目,因为观察程序从正在监视的设备接收更新。 收到更新通知时,更新后的信息将作为 DeviceInformationUpdate 对象提供。 若要更新设备列表,请先找到已更改的相应 DeviceInformation 然后为该对象调用 Update 方法,提供 DeviceInformationUpdate 对象。 这是一个便捷函数,它将自动更新 DeviceInformation 对象。

由于 DeviceWatcher 在设备到达时以及设备更改时发送通知,因此当你对 AssociationEndpoint、AssociationEndpointContainerAssociationEndpointService 对象感兴趣时,你应该使用此方法来枚举设备,因为它们通过网络或无线协议进行枚举。

若要创建 DeviceWatcher,请使用 CreateWatcher 方法之一。 这些方法重载,使你能够指定感兴趣的设备。 为此, 可以提供 DeviceClass 或传入设备选择器。 设备选择器是一个 AQS 字符串,用于指定要枚举的设备。 有关详细信息,请参阅 生成设备选择器。 还可以指定要为设备检索的属性并感兴趣。 如果这样做,指定的属性将出现在集合中返回的每个 DeviceInformation 对象的属性包中。 请务必注意,并非所有属性都可用于所有设备类型。 若要查看哪些属性可用于哪些设备类型,请参阅 设备信息属性

将设备作为后台任务监视

将设备作为后台任务监视与创建 DeviceWatcher 非常相似,如上所述。 事实上,仍需先创建普通 DeviceWatcher 对象,如上一部分所述。 创建它后,将调用 GetBackgroundTrigger 而不是 DeviceWatcher.Start 调用 GetBackgroundTrigger 时,必须指定感兴趣的通知:添加、删除或更新。 如果不请求添加,则无法请求更新或删除。 注册触发器后, DeviceWatcher 将立即在后台运行。 从这一点开始,每当它收到与条件匹配的应用程序的新通知时,后台任务将触发,并且它将提供自上次触发应用程序以来的最新更改。

重要说明 DeviceWatcherTrigger 首次触发应用程序时,观察程序到达 EnumerationCompleted 状态。 这意味着它将包含所有初始结果。 每当它触发应用程序时,它只会包含自上次触发器以来发生的添加、更新和删除通知。 这与前台 DeviceWatcher 对象略有不同,因为初始结果不会一次传入,并且仅在到达 EnumerationCompleted才会在捆绑包中传递。

 

如果某些无线协议在后台扫描与前台扫描,或者它们可能根本不支持在后台扫描,则它们的行为有所不同。 与后台扫描有关,有三种可能性。 下表列出了可能对应用程序产生的可能性和影响。 例如,蓝牙和 Wi-Fi Direct 不支持后台扫描,因此通过扩展,它们不支持 DeviceWatcherTrigger

行为 影响
后台的相同行为
仅在后台可能进行被动扫描 等待被动扫描发生时,设备可能需要更长的时间才能发现。
不支持后台扫描 DeviceWatcherTrigger 不会检测到任何设备,也不会报告任何更新。

 

如果 DeviceWatcherTrigger 包含不支持作为后台任务进行扫描的协议,则触发器仍将有效。 但是,将无法通过该协议获取任何更新或结果。 其他协议或设备的更新仍会正常检测到。

使用 DeviceInformationKind

在大多数情况下,无需担心 DeviceInformation 对象的 DeviceInformationKind。 这是因为你正在使用的设备 API 返回的设备选择器通常保证你获得用于其 API 的正确设备对象类型。 但是,在某些情况下,需要获取 设备的 DeviceInformation ,但没有相应的设备 API 来提供设备选择器。 在这些情况下,需要生成自己的选择器。 例如,设备上的 Web 服务没有专用 API,但你可以发现这些设备,并使用 Windows.Devices.Enumeration API 获取有关这些设备的信息,然后使用套接字 API 使用这些设备。

如果要构建自己的设备选择器来枚举设备对象, DeviceInformationKind 对你来说非常重要。 DeviceInformationKind 的参考页上描述了所有可能的种类以及它们彼此之间的关系。 DeviceInformationKind 的最常见用途之一是指定在将查询与设备选择器一起提交查询时要搜索的设备类型。 这样做可确保仅枚举与提供的 DeviceInformationKind 匹配的设备。 例如,可以找到 DeviceInterface 对象,然后运行查询以获取父 Device 对象的信息。 该父对象可能包含其他信息。

请务必注意,DeviceInformation 对象的属性包中可用的属性将因设备的 DeviceInformationKind 而异。 某些属性仅适用于某些类型。 有关哪些属性可用于哪些类型的详细信息,请参阅 设备信息属性。 因此,在上面的示例中,搜索父设备将提供对 DeviceInterface 设备对象中不可用的详细信息的访问权限。 因此,在创建 AQS 筛选器字符串时,请务必确保请求的属性可用于要枚举的 DeviceInformationKind 对象。 有关生成筛选器的详细信息,请参阅 生成设备选择器

枚举 AssociationEndpoint、AssociationEndpointContainerAssociationEndpointService 对象时,需要通过无线或网络协议进行枚举。 在这些情况下,建议不要使用 FindAllAsync,而是使用 CreateWatcher 这是因为通过网络进行搜索通常会导致搜索操作在生成 EnumerationCompleted 之前不会超时 10 秒或更多秒。 在触发 EnumerationCompleted 之前,FindAllAsync 不会完成其操作。 如果使用 DeviceWatcher,无论何时调用 EnumerationCompleted,结果都会更接近实时

保存设备供以后使用

任何 DeviceInformation 对象都由两个信息片段的组合进行唯一标识:DeviceInformation.Id DeviceInformation.Kind 如果保留这两条信息,可以通过向 CreateFromIdAsync 提供此信息来重新创建 DeviceInformation 对象。 如果执行此操作,可以保存与应用集成的设备的用户首选项。