【发布时间】:2012-02-27 15:36:26
【问题描述】:
我想在插入/移除/启用/禁用 USB 设备时收到通知。 我正在为Win32_USBControllerDevice 注册“__InstanceOperationEvent”。
问题是,虽然我收到了所有设备的插入/删除通知。 我仅获得 USB 存储设备的启用/禁用事件。
我做错了什么?
提前致谢
【问题讨论】:
我想在插入/移除/启用/禁用 USB 设备时收到通知。 我正在为Win32_USBControllerDevice 注册“__InstanceOperationEvent”。
问题是,虽然我收到了所有设备的插入/删除通知。 我仅获得 USB 存储设备的启用/禁用事件。
我做错了什么?
提前致谢
【问题讨论】:
如果不提供代码示例或告诉我们您使用的语言,您可能很难理解您在说什么。
Win32_USBController 类是 Win32_PnPEntity 类的关联者,该类具有所有 USB 设备的实例,无论其类型如何。因此,此类的__InstanceOperationEvent 确实为所有设备提供通知,而不仅仅是 USB 存储设备。更恰当地说,它适用于任何 PnP 兼容的 USB 设备。
以下脚本是用 VBScript 编写的概念点。当设备连接或断开连接时,它将通知您所有 USB 组件。我使用 USB 存储设备、USB 鼠标和键盘以及我身边的各种其他设备进行了测试。他们都工作了。我在 Vista x64 上进行了测试,但这应该适用于任何版本的 Windows。
vbscript示例:
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colEvents = objWMIService.ExecNotificationQuery _
("Select * From __InstanceOperationEvent Within 1 " _
& "Where TargetInstance Isa 'Win32_USBControllerDevice'")
While True
Set objEvent = colEvents.NextEvent
Select Case objEvent.Path_.Class
Case "__InstanceCreationEvent"
strOutput = "Device inserted:" & vbCr
Case "__InstanceDeletionEvent"
strOutput = "Device removed:" & vbCr
Case Default
strOutput = objEvent.Path_.Class & vbCr
End Select
strDeviceName = objEvent.TargetInstance.Dependent
strDeviceName = Replace(strDeviceName, Chr(34), "")
arrDevicePart = Split(strDeviceName, "=")
strDeviceName = arrDevicePart(1)
Set colUSBDevices = objWMIService.ExecQuery _
("Select * From Win32_PnPEntity Where DeviceID = '" & strDeviceName & "'")
For Each objUSBDevice in colUSBDevices
strOutput = strOutput & objUSBDevice.Description & vbCr
Next
WScript.Echo strOutput
Wend
确定何时启用或禁用设备是类似的,但有一些明显的区别。您将需要使用 Win32_PnPEntity 类,它基本上是所有已安装 PnP 设备的枚举。您需要关注每个实例的 ConfigManagerErrorCode 属性。这提供的信息与您在设备管理器的设备状态部分中找到的信息相同。您可以看到为什么在任何给定设备上观看此属性很有用。当设备更改为显示正常操作的代码 (0) 时,我们可以安全地假设设备已启用。当此代码更改为代码 22 时,我们知道设备已被禁用。 (所有其他代码都表示错误状态。)__InstanceModificationEvent 是监视Win32_PnPEntity 类的任何实例中的更改的好选择。
如果您对可能的错误代码感兴趣,可以在脚本开头附近输入WScript.Echo 语句,它会在其中枚举所有可能的值。
vbscript示例:
Const wbemFlagUseAmendedQualifiers = &H20000
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objPnPEntityClass = objWMIService.Get("Win32_PnPEntity", wbemFlagUseAmendedQualifiers)
arrValues = objPnPEntityClass.properties_("ConfigManagerErrorCode").qualifiers_("values")
valueMap = objPnPEntityClass.properties_("ConfigManagerErrorCode").qualifiers_("valuemap")
WScript.Echo "Gathering Device Manager error codes..."
Set dictErrorCodes = CreateObject("Scripting.Dictionary")
For i = 0 to Ubound(arrValues)
dictErrorCodes.add valueMap(i), arrValues(i)
' 0, This device is working properly.
' 22, This device is disabled.
Next
Set objPnPEntityClass = Nothing
WScript.Echo "Setting up event notification..."
Set colEvents = objWMIService.ExecNotificationQuery _
("Select * From __InstanceModificationEvent Within 1 " _
& "Where TargetInstance Isa 'Win32_PnPEntity'")
WScript.Echo "Waiting..."
While True
Set objEvent = colEvents.NextEvent
Set objDevice = objEvent.TargetInstance
Select Case objDevice.ConfigManagerErrorCode
Case 0 ' This device is working properly.
strOutput = objDevice.Caption & " is working properly." & vbCr
Case 22 ' This device is disabled.
strOutput = objDevice.Caption & " has been disabled." & vbCr
Case Default
strDeviceStatus = arrValues(objDevice.ConfigManagerErrorCode)
strOutput = "(" & objDevice.Caption & ") " & strDeviceStatus & vbCr
End Select
WScript.Echo strOutput
Wend
【讨论】:
Win32_PnPEntity 确实适用于我的 USB 指纹扫描仪设备。 但是它不会选择未安装驱动程序的设备的事件。我也给出了我的代码,可能我的代码有问题。
static void Main(string[] args)
{
WqlEventQuery weqQuery = new WqlEventQuery();
weqQuery.EventClassName = "__InstanceOperationEvent";
weqQuery.WithinInterval = new TimeSpan(0, 0, 3);
weqQuery.Condition = @"TargetInstance ISA 'Win32_PnPEntity'";
ManagementEventWatcher m_mewWatcher = new ManagementEventWatcher(weqQuery);
m_mewWatcher.EventArrived += new EventArrivedEventHandler(m_mewWatcher_EventArrived);
m_mewWatcher.Start();
m_mewWatcher1.Start();
Console.ReadLine();
}
static void m_mewWatcher_EventArrived(object sender, EventArrivedEventArgs e)
{
bool bUSBEvent = false;
foreach (PropertyData pdData in e.NewEvent.Properties)
{
try
{
ManagementBaseObject mbo = (ManagementBaseObject)pdData.Value;
if (mbo != null)
{
foreach (PropertyData pdDataSub in mbo.Properties)
{
Console.WriteLine("pdDataSub.Name= " + pdDataSub.Name + " and pdDataSub.Value.ToString() = " + (pdDataSub.Value == null ? "" : pdDataSub.Value));
}
}
}
catch (Exception ex)
{
}
}
}
【讨论】: