快速入门:枚举常用设备 (HTML)
[ 本文适用于编写 Windows 运行时应用的 Windows 8.x 和 Windows Phone 8.x 开发人员。如果你要针对 Windows 10 进行开发,请参阅 最新文档 ]
Windows.Devices.Enumeration 命名空间提供枚举设备的两种方法:FindAllAsync 和 CreateWatcher。 FindAllAsync 对可用设备执行一次性搜索,它最适合在用户添加、删除或更改设备时不需要更新的应用。 当用户在操作系统完成初始枚举后添加、删除或更改设备时 CreateWatcher 会枚举设备,还会引发通知事件。 以下我们说明如何使用 FindAllAsync 对常用设备执行一次性枚举。
目标: 通过使用 Windows.Devices.Enumeration 命名空间,列出常见设备类别中的可用设备。
先决条件
我们假定你熟悉 JavaScript 和 HTML。
完成所需时间: 20 分钟.
说明
1. 打开 Microsoft Visual Studio
打开 Visual Studio 的一个实例。
2. 创建新项目
在“新建项目”对话框中,从“JavaScript”项目类型中,选取一个空白应用。
3. 插入应用 HTML
打开 Default.html 并将此代码复制到文件中,替换文件的内容。
此 HTML 提供一个用户界面,允许用户从要枚举的七种设备类型中选择:麦克风、音频播放、摄相机、可移动存储、MTP 设备服务、SMS 设备和邻近设备。
<!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. 插入应用 JavaScript
打开文件 Default.js,然后插入此代码。
基于用户所选择的设备类型,onEnumerateDeviceInterface 函数会选择一个 DeviceClass 值,或从 getDeviceSelector 函数获取一个选择器字符串。该应用接着会将此值传递给 FindAllAsync。如果枚举成功,那么 successCallback 函数会输出设备信息,而如果枚举失败,errorCallback 函数会输出一条错误消息。
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 />";
}
注意
对于前四个选项,你可以将 DeviceClass 枚举值传递给 FindAllAsync。这等同于从与设备类型相关联的 Windows 运行时 API 获取选择器字符串,然后将选择器传递给 FindAllAsync。在 switch 语句中的相关情形内会注释掉使用选择器字符串而不是 DeviceClass 枚举的代码。
对于最后三个选项,不存在任何 DeviceClass 枚举值,因此仅会显示获取相应的选择器字符串的 API 调用。
5. 生成应用
在“生成”菜单上,单击“生成解决方案”****生成项目。
6. 测试应用
- 在“调试”菜单上,单击“启动调试”****测试该解决方案。
- 选取要枚举的设备接口类。
- 单击“枚举”按钮以开始搜索属于指定设备接口类的设备接口。应用会在设备接口所创建页的下半部分中列出这些设备接口。
7. 添加你自己的设备功能(可选)
若要开始访问设备功能而不仅仅是列出设备,请将你已枚举的设备的 DeviceInformation.id 属性传递给 Windows 运行时 API 以使用该设备。例如,你可以使用已枚举的摄像头的 ID 来设置Windows.Media.Capture.MediaCaptureInitializationSettings.VideoDeviceId 属性,以指定摄像头用于视频捕获。
将你需要的功能添加到项目的 package.appxmanifest 文件。
通过将设备 ID 传递给你可以用于与设备进行交互的 API 来开始。存在一些采用设备 ID 来初始化对象以使用设备的方法。
- Windows.Media.Capture.MediaCaptureInitializationSettings.AudioDeviceId
- Windows.Media.Capture.MediaCaptureInitializationSettings.VideoDeviceId
- Windows.Devices.Portable.StorageDevice.FromId
- Windows.Devices.Sms.SmsDevice.FromIdAsync
- Windows.Networking.Proximity.ProximityDevice.FromId
对于使用 MTP 设备服务的 WPD 设备(已使用 Windows.Devices.Portable.ServiceDevice.GetDeviceSelector 或 Windows.Devices.Portable.ServiceDevice.GetDeviceSelectorFromServiceId 进行枚举),你可以创建一个 COM 自动化对象以使用类似以下的设备:
deviceFactory = new ActiveXObject("PortableDeviceAutomation.Factory");
var device = deviceFactory.getDeviceFromId(deviceId);
摘要和后续步骤
你刚才已学习了如何通过将某个 Windows.Device.Enumeration.DeviceClass 枚举值或 getDeviceSelector 方法中的某个选择器字符串传递给 findAllAsync 来枚举常见类型设备。
如果你需要的设备接口类不在 Windows.Device.Enumeration.DeviceClass 枚举内,且不存在任何 Windows 运行时 API 来为你获取选择器,那么你将必须自己生成一个高级查询语法 (AQS) 字符串并将其传递给 findAllAsync。
若要为指定类型的可用设备构建一个查询,你需要了解设备类 GUID。此处的代码包含属于由用户在输入框中键入的 GUID 指定的设备接口类的可用设备的查询。GUID 的格式必须为:“{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}”。
注意 确保在选择器字符串中用引号将 GUID 引起来。例如,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.
}
注意 此示例执行一次性枚举,但当用户添加、删除或更改设备时,对于需要更新其用户界面的应用而言,仅执行此操作仍不够。下一主题将介绍如何使用 CreateWatcher 以便可以枚举设备和获得设备通知。
相关主题
为枚举提供选择器字符串的 Windows 运行时 API
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
用于生成选择器字符串的高级查询语法 (AQS)