Quickstart: enumerating commonly used devices (XAML)

The Windows.Devices.Enumeration namespace provides two methods for enumerating devices: FindAllAsync and CreateWatcher. FindAllAsync performs a one-time search for available devices. We recommend FindAllAsync for apps that don't need updates when a user adds, deletes, or changes a device. CreateWatcher enumerates devices and also raises notification events when a user adds, deletes, or changes a device after the operating system completes the initial enumeration. Here we show you how to do a one-time enumeration of commonly used devices using FindAllAsync.

Objective: To list available devices in common device categories, by using the Windows.Devices.Enumeration namespace.

Prerequisites

We assume that you are familiar with Visual C# and XAML.

Time to complete: 20 minutes.

Instructions

1. Open Microsoft Visual Studio

Open an instance of Microsoft Visual Studio.

2. Create a new project

In the New Project dialog box, from the Visual C#/Windows Store style project types, pick a Blank Application.

3. Insert the app XAML

Open your BlankPage.xaml and copy this code into the file, replacing the file's contents.

This XAML provides a user interface that lets users select from three types of devices to enumerate: webcams, portable devices, and printers.

<Page
    x:Class="Application1.BlankPage"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Application1"
    xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid x:Name="ContentRoot" Background="Black" Margin="100,20,100,20">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <!-- Header -->
        <StackPanel x:Name="Header" Grid.Row="0">
            <StackPanel Orientation="Horizontal"/>
        </StackPanel>

        <!-- Content -->
        <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Grid.Row="1" ZoomMode="Disabled">
            <StackPanel x:Name="ContentPanel">
                <StackPanel x:Name="InputPanel" Orientation="Horizontal" HorizontalAlignment="Left">
                    <StackPanel/>
                    <StackPanel Margin="0,31,0,0" >
                        <StackPanel x:Name="Description" MaxWidth="900">

                            <!-- Device Interfaces -->
                            <StackPanel x:Name="DeviceInterfacesInput">

                                <TextBlock Text="Input" Margin="0,25,0,20" />

                                <TextBlock TextWrapping="Wrap" Text="This scenario demonstrates using the device enumeration interface to look for specific device interfaces. A device interface is the programmatic entry point for a device." HorizontalAlignment="Left"/>
                                <TextBlock TextWrapping="Wrap" Margin="0,10,0,0" Text="Enter a device interface class GUID directly in the field below:" HorizontalAlignment="Left"/>
                                <StackPanel Orientation="Horizontal" Margin="0,10,0,0"/>
                                <StackPanel Orientation="Horizontal" Margin="0,10,0,0">
                                    <TextBlock Text="Interface Class GUID:" HorizontalAlignment="Left" VerticalAlignment="Center" />
                                    <TextBox Name="InterfaceClassGuid" Margin="10,0,0,0" MinWidth="350" />
                                </StackPanel>

                                <TextBlock TextWrapping="Wrap" Text="...or select from some typical interface classes:" Margin="10,10,0,0" Width="888" />
                                <ListBox Name="InterfaceClasses">
                                    <ListBoxItem Name="WebcamInterfaceClass">Webcams</ListBoxItem>
                                    <ListBoxItem Name="WpdInterfaceClass">Portable Devices</ListBoxItem>
                                    <ListBoxItem Name="PrinterInterfaceClass">Printers</ListBoxItem>

                                </ListBox>
                                <TextBlock TextWrapping="Wrap" Text="By clicking the enumerate button, you start a search for device interfaces that belong to the specified device interface class. The device interface will be listed below." Margin="10,10,0,0" Width="888" Height="35" />
                                <Button Name="EnumerateInterfacesButton" Content="Enumerate" Margin="0,10,10,0" Click="EnumerateDeviceInterfaces" />
                            </StackPanel>

                        </StackPanel>
                    </StackPanel>
                </StackPanel>

                <!-- Output section -->
                <TextBlock Text="Output" Margin="0,25,0,20" />
                <StackPanel x:Name="Output"  HorizontalAlignment="Left">
                    <TextBlock Name="OutputText" />

                    <!-- Device Interfaces-->
                    <ListBox Name="DeviceInterfacesOutputList" IsEnabled="False" BorderThickness="0" />

                </StackPanel>
            </StackPanel>
        </ScrollViewer>

    </Grid>
</Page>

4. Insert the app C#

Open your project's BlankPage.xaml.cs file and replace the existing code with this code.

Based on the device type selected by the user, the EnumerateDeviceInterfaces function builds a string and then passes this string to FindAllAsync. The app outputs the number of device interfaces found and lists the devices.

using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Media.Imaging;

using Windows.Devices.Enumeration;
using Windows.Devices.Enumeration.Pnp;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238

namespace Application1
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class BlankPage : Page
    {
        public BlankPage()
        {
            this.InitializeComponent();
            InterfaceClasses.SelectionChanged += new SelectionChangedEventHandler(InterfaceClasses_SelectionChanged);
        }

        void InterfaceClasses_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (InterfaceClasses.SelectedItem == PrinterInterfaceClass)
            {
                InterfaceClassGuid.Text = "{0ECEF634-6EF0-472A-8085-5AD023ECBCCD}";
            }
            else if (InterfaceClasses.SelectedItem == WebcamInterfaceClass)
            {
                InterfaceClassGuid.Text = "{E5323777-F976-4F5B-9B55-B94699C46E44}";
            }
            else if (InterfaceClasses.SelectedItem == WpdInterfaceClass)
            {
                InterfaceClassGuid.Text = "{6AC27878-A6FA-4155-BA85-F98F491D4F33}";
            }
        }

        async void EnumerateDeviceInterfaces(object sender, RoutedEventArgs eventArgs)
        {
            EnumerateInterfacesButton.IsEnabled = false;
            DeviceInterfacesOutputList.Items.Clear();
            try
            {
                var selector = "System.Devices.InterfaceClassGuid:=\"" + InterfaceClassGuid.Text + "\"";
                //                 + " AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True";
                var interfaces = await DeviceInformation.FindAllAsync(selector, null);
                OutputText.Text = interfaces.Count + " device interface(s) found\n\n";
                foreach (DeviceInformation deviceInterface in interfaces)
                {
                    DisplayDeviceInterface(deviceInterface);
                }
            }
            catch (ArgumentException)
            {
                //The ArgumentException gets thrown by FindAllAsync when the GUID isn't formatted properly
                //The only reason we're catching it here is because the user is allowed to enter GUIDs without validation
                //In normal usage of the API, this exception handling probably wouldn't be necessary when using known-good GUIDs 
                OutputText.Text = "Caught ArgumentException. Verify that you've entered a valid interface class GUID.";
            }
            EnumerateInterfacesButton.IsEnabled = true;
        }

        async void DisplayDeviceInterface(DeviceInformation deviceInterface)
        {
            var id = "Id:" + deviceInterface.Id;
            var name = deviceInterface.Name;
            var isEnabled = "IsEnabled:" + deviceInterface.IsEnabled;
            var item = id + " is \n" + name + " and \n" + isEnabled;
            DeviceInterfacesOutputList.Items.Add(item);
        }

    }

}

5. Build the app

On the Build menu, click Build Solution to build the project.

6. Test the app

  1. On the Debug menu, click Start Debugging to test the solution.
  2. Enter a device interface class GUID or pick the device interface class to enumerate.
  3. Click the Enumerate button to start a search for device interfaces that belong to the specified device interface class. The app outputs the number of device interfaces and lists the device interfaces in the lower half of the page that it creates.

Summary and next steps

You just learned how to enumerate common types of devices, by passing a selector string to findAllAsync.

You can pass a device interface class from the Windows.Device.Enumeration.DeviceClass enumeration to findAllAsync, or you can use a Windows Runtime API to get a selector to pass to findAllAsync, or you can build an Advanced Query Syntax (AQS) string and pass it to findAllAsync.

Note  This sample did a one-time enumeration, but this won't be enough for an app that needs to update its user interface when a user adds, removes, or changes a device. The next topic shows you how to use CreateWatcher so you can enumerate devices and get device notifications.

 

How to enumerate dynamically

Windows Runtime APIs that provide selector strings for enumeration

Windows.Media.Devices.MediaDevice.getAudioCaptureSelector

Windows.Media.Devices.MediaDevice.getAudioRenderSelector

Windows.Media.Devices.MediaDevice.getVideoCaptureSelector

Windows.Media.Devices.MediaDevice.getDefaultAudioRenderId

Windows.Media.Devices.MediaDevice.getDefaultAudioCaptureId

Windows.Devices.Portable.StorageDevice.GetDeviceSelector

Windows.Devices.Portable.ServiceDevice.GetDeviceSelector

Windows.Devices.Portable.ServiceDevice.GetDeviceSelectorFromServiceId

Windows.Devices.Sms.SmsDevice.GetDeviceSelector

Windows.Networking.Proximity.ProximityDevice.GetDeviceSelector

Advanced Query Syntax (AQS) for building selector strings

Using Advanced Query Syntax Programmatically