Quickstart: enumerating commonly used devices (HTML)

The Windows.Devices.Enumeration namespace provides two methods for enumerating devices: FindAllAsync and CreateWatcher. FindAllAsync does a one-time search for available devices and is best for apps that don't need updates if 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 JavaScript and HTML.

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 JavaScript project types, pick a blank app.

3. Insert the app HTML

Open your Default.html and copy this code into the file, replacing the file's contents.

This HTML provides a user interface that lets users select from seven types of devices to enumerate: microphones, audio playback, webcams, removable storage, MTP device services, SMS devices, and proximity devices.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <script src="/js/default.js"></script>
</head>
<body data-design-activate="defaultPage.activated">
    <h1>Device Enumeration Sample</h1>

    <h2 >Input</h2>

    <div>            

        <div id="Input">
           <p>This scenario demonstrates using the device enumeration API
              to look for specific device interfaces. A device interface
              is the programmatic entry point for a device.</p>
           <p>Select a device interface class</p>
                <select id="SelectInterfaceClass" size="7" >
                    <option value="audioCapture">Audio Capture</option>
                    <option value="audioRender">Audio Playback</option>
                    <option value="videoCapture">Webcams</option>
                    <option value="portableStorageDevice">Portable Storage</option>
                    <option value="mtpService">MTP Device Service</option>
                    <option value="sms">SMS Device</option>
                    <option value="proximity">Proxmity Device</option>
                </select>
                <br />
                <p>Clicking the enumerate button will start a search for 
                 device interfaces that belong to the specified device interface class. 
                 The device interfaces will be listed below.</p>
          <input onclick="onEnumerateDeviceInterfaces()" type="button" value="Enumerate" />
                <br /><br />
            </div>
    </div>


    <h2> Output</h2>

            <div id="statusMessage"></div>

            <!-- Device Enumeration results are displayed in this element -->
            <div  id="Output"></div>
</body>
</html>

4. Insert the app JavaScript

Open the file Default.js, and insert this code.

Based on the device type selected by the user, the onEnumerateDeviceInterface function chooses a DeviceClass value or gets a selector string from a getDeviceSelector function. The app then passes this value to FindAllAsync. The successCallback function prints device info if enumeration succeeds, and the errorCallback function prints an error message if enumeration fails.

function onEnumerateDeviceInterfaces() {
    document.getElementById("Output").innerHTML = ""; // clear output
    try {
        var selection = document.getElementById("SelectInterfaceClass");
        var selectedDeviceClass = 
            selection.options[selection.selectedIndex].value;
        var deviceClass;
        var Enumeration = Windows.Devices.Enumeration;
        var selectorString = "";

        var mtpServiceDevice = Windows.Devices.Portable.ServiceDevice;
        var smsDevice = Windows.Devices.Sms.SmsDevice;
        var proximityDevice = Windows.Networking.Proximity.ProximityDevice;
        switch (selectedDeviceClass) {
            case "audioCapture":
                // same as:
                // var mediaDevice = Windows.Media.Devices.MediaDevice;
                // selectorString =  mediaDevice.getAudioCaptureSelector();
                deviceClass = Enumeration.DeviceClass.audioCapture;
                break;
            case "audioRender":
                // same as:
                // var mediaDevice = Windows.Media.Devices.MediaDevice;
                // selectorString =  mediaDevice.getAudioRenderSelector();
                deviceClass = Enumeration.DeviceClass.audioRender;
                break;
            case "portableStorageDevice":
                // same as: 
                // var storageDevice = Windows.Devices.Portable.StorageDevice;
                // selectorString = storageDevice.getDeviceSelector();
                deviceClass = Enumeration.DeviceClass.portableStorageDevice;
                break;
            case "videoCapture":
                // same as:
                // var mediaDevice = Windows.Media.Devices.MediaDevice;
                // selectorString =  mediaDevice.getVideoCaptureSelector();
                deviceClass = Enumeration.DeviceClass.videoCapture;
                break;
            case "mtpService":
            // Windows.Devices.Portable.ServiceDevice.getDeviceSelector
                selectorString = mtpServiceDevice.getDeviceSelector(Windows.Devices.Portable.ServiceDeviceType.calendarService);
                break;
            case "sms":
            // Windows.Devices.Sms.SmsDevice.getDeviceSelector
                selectorString = smsDevice.getDeviceSelector();
                break;
            case "proximity":
            // Windows.Networking.Proximity.ProximityDevice.getDeviceSelector
                selectorString = proximityDevice.getDeviceSelector();
                break;
            case "imageScanner":
            // same as:
            // var scannerDevice = Windows.Devices.Scanners.ImageScanner;
            // selectorString = scannerDevice.getDeviceSelector();
                deviceClass = Enumeration.DeviceClass.imageScanner;
                break;
            default: deviceClass = Enumeration.DeviceClass.all;
        }

        var DeviceInformation = Enumeration.DeviceInformation;
        if (selectorString == "") {
            DeviceInformation.findAllAsync(deviceClass).then(
                successCallback, 
                errorCallback
            );
        } else {
            DeviceInformation.findAllAsync(selectorString, null).then(
                successCallback, 
                errorCallback
            );
        }
    } catch (e) {
        document.getElementById("statusMessage").innerHTML = 
            "Failed to enumerate devices, error: " + e.message;
    }
}

// Handles successful completion of the findAllAsync method.
function successCallback(deviceInformationCollection) {
    var numDevices = deviceInformationCollection.length;
    document.getElementById("statusMessage").innerHTML = 
        numDevices + " device interface(s) found";
    if (numDevices) {
        for (var i = 0; i < numDevices; i++) {
            printFriendlyNameAndID(deviceInformationCollection[i], 
                document.getElementById("Output"));
        }
    } else {
        document.getElementById("statusMessage").innerHTML = "No devices found";
    }
}

// Handles an error completion of the findAllAsync method.
function errorCallback(e) {
    document.getElementById("statusMessage").innerHTML = 
        "Failed to find devices, error: " + e.message;
}

// Prints the friendly name of the device interface and its ID 
// The ID is the device interface path.
function printFriendlyNameAndID(deviceInterface, log) {

    // The name property is equivalent to System.ItemNameDisplay property
    log.innerHTML += "<h3>" + 
            deviceInterface.name + "<h3/>";
    log.innerHTML += "<p>Interface ID: " + deviceInterface.id;    
    log.innerHTML += "<p>Enabled: " + deviceInterface.isEnabled;
    
    log.innerHTML += "<br />";
}

Note  

For the first four choices, you can pass a DeviceClass enumeration value to FindAllAsync. This is equivalent to getting a selector string from the Windows Runtime API associated with the device type, and passing the selector to FindAllAsync. The code for using the selector string instead of the DeviceClass enumeration is commented out within the relevant cases in the switch statement.

For the last three choices, there is no DeviceClass enumeration value, so only the API call for getting the appropriate selector string is shown.

 

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. 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 lists the device interfaces in the lower half of the page that it creates.

7. Add your own device functionality (optional)

To start accessing device functionality rather than just listing devices, pass the DeviceInformation.id property of a device that you enumerated to the Windows Runtime API for using the device. For instance, you can use the ID of an enumerated webcam to set the Windows.Media.Capture.MediaCaptureInitializationSettings.VideoDeviceId property, to specify the webcam to use for video capture.

  1. Add the capabilities you need to the project's package.appxmanifest file.

  2. Start by passing the device ID to an API you can use for interacting with the device. These are some methods that take a device ID to initialize an object for using a device:

    For WPD devices that use an MTP device service (enumerated using Windows.Devices.Portable.ServiceDevice.GetDeviceSelector or Windows.Devices.Portable.ServiceDevice.GetDeviceSelectorFromServiceId), you can create a COM Automation object to work with the device like this:

    deviceFactory = new ActiveXObject("PortableDeviceAutomation.Factory");

    var device = deviceFactory.getDeviceFromId(deviceId);

Summary and next steps

You just learned how to enumerate common types of devices, by passing either a Windows.Device.Enumeration.DeviceClass enumeration value or a selector string from a getDeviceSelector method to findAllAsync.

If the device interface class you want isn't in the Windows.Device.Enumeration.DeviceClass enumeration, and there is no Windows Runtime API to get a selector for you, you have to build an Advanced Query Syntax (AQS) string yourself and pass it to findAllAsync.

To build a query for available devices of a specified type, you need to know the device class GUID. The code here includes a query for available devices belonging to a device interface class that is specified by a GUID the user has typed into an input box. The GUID must be in the format "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}".

Note  Ensure that the GUID is enclosed in quotes within the selector string. For example, var selectorString = "System.Devices.InterfaceClassGuid:=\"{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\"";

 

        if (textinput.value != ""){
            var textDeviceInterfaceClassGUID = textinput.value;
            var selectorString = "System.Devices.InterfaceClassGuid:=\"" + 
                textDeviceInterfaceClassGUID + 
                "\" AND System.Devices.InterfaceEnabled:=true";
            var Enum = Windows.Devices.Enumeration;
            Enum.DeviceInformation.findAllAsync(selectorString, null).then(
                    successCallback, 
                    errorCallback
                );

// Handles successful completion of the findAllAsync method.
function successCallback(deviceInformationCollection) {
    // Add your code here for processing the enumerated device collection.
}

// Handles an error completion of the findAllAsync method.
function errorCallback(e) {
    // Add your error-handling code here.
}

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