我一直在编写一些代码来检测USB设备的添加和删除,并且使用以下WMI代码注册设备更改通知:

watcher = new ManagementEventWatcher(query);
watcher.EventArrived += new EventArrivedEventHandler(DeviceChangeEventReceived);
watcher.Start();

这是处理程序代码:
void DeviceChangeEventReceived(object sender, EventArrivedEventArgs e)
{
   foreach (PropertyData pd in e.NewEvent.Properties)
   {
      Log.Debug("\t" + pd.Name + ":" + pd.Value + "\t" + pd.Value.GetType());
   }
}

一切都很好,它适用于我插入或从系统中卸下的任何USB设备。我遇到的问题是,如何识别引起事件的设备?

在程序的其他地方,我保留了我最感兴趣的当前连接设备的列表,因此,如果发生设备删除事件,我可以使用“select * from Win32_PnPEntity”或其他一些方法针对WMI检查该列表。类似的查询。但是,这是识别被删除设备的非常不准确且繁琐的方式。附加的问题是,除非我提前缓存了Win32_PnPEntity的整个列表,并且确实进行了疯狂的比较/验证,否则我无法准确地知道添加了什么设备。

我在这里遗漏明显的东西吗?如何将设备更改事件关联到特定设备?

更新:我仍然没有为这个问题提供理想的解决方案,但是我正在做的是在内存中维护一个当前连接的设备(我感兴趣的设备)列表,以及每次处理一个事件时(请参见上面),我查询Win32_PnPEntity来查看存储在已连接设备列表中的设备是否仍处于连接状态。这是次优的解决方案,因为似乎无法从指示“设备更改事件”的事件中获取任何特定的设备标识信息,这很奇怪。似乎非常奇怪,该信息不可用。叹

最佳答案

好的,因此,在进行了进一步的研究和实验之后,我发现我需要使用其他WMI查询来解决我的问题,即将设备更改事件与特定设备相关联。在这种情况下,我需要找到WMI中通常称为“TargetInstance”的内容。

因此,我改用以下WMI查询代码

            ManagementEventWatcher watcher;
            string queryStr =
                "SELECT * FROM __InstanceCreationEvent " +
                "WITHIN 2 "
              + "WHERE TargetInstance ISA 'Win32_PnPEntity'"

            watcher = new ManagementEventWatcher(queryStr);
            watcher.EventArrived += new EventArrivedEventHandler(DeviceChangeEventReceived);
            watcher.Start();

因此,这里的区别在于__InstanceCreationEvent具有一个名为“TargetInstance”的属性,该属性正是我想要的。我将TargetInstance属性转换为ManagementBaseObject(类型为“Win32_PnPEntity”(根据上面的查询中的ISA子句)),瞧,我得到了创建的特定设备。

关于我的原始查询“Select * from Win32_DeviceChangeEvent”如何对所有人都有用仍然感到困惑,因为在触发通用事件通知后没有提供其他信息。无论哪种方式,此新查询都可以明显解决我的问题。 WMI似乎很强大,但是找到要使用的正确查询可能很棘手,并且需要进行一些试验。

10-07 19:26
查看更多