如何获取有关最近连接的USB设备的信息?

5
我可以捕获USB设备连接事件,使用Win32_DeviceChangeEvent,但只允许查看3个属性。
class Win32_DeviceChangeEvent : __ExtrinsicEvent
{
  uint8  SECURITY_DESCRIPTOR[];
  uint64 TIME_CREATED;
  uint16 EventType;
};

但我不明白如何获取有关此设备的全部信息。具体来说,它的端口和集线器、VirtualHubAdress名称等。
public enum EventType
{
    Inserted = 2,
    Removed = 3
}

public static void RegisterUsbDeviceNotification()
{
    var watcher = new ManagementEventWatcher();
    var query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
    //watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
    watcher.EventArrived += (s, e) =>
    {
        //here is im need to get info about this device

        EventType eventType = (EventType)(Convert.ToInt16(e.NewEvent.Properties["EventType"].Value));
    };

    watcher.Query = query;
    watcher.Start();
}

也许我可以使用类似这样的东西来做。
[DllImport("UseFull.dll")] 
private IntpPtr GetAllinfo(params);
3个回答

7

Win32_DeviceChangeEvent报告了事件的类型和事件的时间(uint64,表示自1601年1月1日UTC以后的100纳秒间隔)。如果您还想知道到底是什么到达或被移除,那么它并没有太多用处。

我建议使用WqlEventQuery类,将其EventClassName设置为__InstanceOperationEvent
这个系统类提供了一个TargetInstance属性,可以将其转换为ManagementBaseObject,这是完整的管理对象,还提供了生成事件的设备的基本信息。
这些信息包括(除了设备的友好名称之外)PNPDeviceID,可以用来构建其他查询以进一步检查所引用的设备。

WqlEventQueryCondition属性可以在这里设置为TargetInstance ISA 'Win32_DiskDrive'
它也可以设置为其他感兴趣的Win32_类。

设置事件监听器(本地机器):
(事件处理程序被称为DeviceChangedEvent

var query = new WqlEventQuery() {
    EventClassName = "__InstanceOperationEvent",
    WithinInterval = new TimeSpan(0, 0, 3),
    Condition = @"TargetInstance ISA 'Win32_DiskDrive'"
};

var scope = new ManagementScope("root\\CIMV2");
using (var moWatcher = new ManagementEventWatcher(scope, query))
{
    moWatcher.Options.Timeout = ManagementOptions.InfiniteTimeout;
    moWatcher.EventArrived += new EventArrivedEventHandler(DeviceChangedEvent);
    moWatcher.Start();
}

事件处理程序在`e.NewEvent.Properties["TargetInstance"]`中接收到表示Win32_DiskDrive类的管理对象。
请参阅此处直接可用的属性的文档。
感兴趣的派生类__InstanceOperationEvent,由e.NewEvent.ClassPath.ClassName报告,可以是:

__InstanceCreationEvent:检测到新设备到达。
__InstanceDeletionEvent:检测到设备移除。
__InstanceModificationEvent:某个现有设备已被修改。

请注意,事件是在一个辅助线程中触发的,我们需要使用BeginInvoke()来更新UI线程上的新信息。
▶ 在这里应该避免使用Invoke(),因为它是同步的:它会阻塞处理程序直到方法完成。此外,在这种情况下,死锁并非完全不可能发生。
请参考这里:获取USB存储设备的序列号,这是一个提供有关设备的大部分可用信息的类(信息已经过滤以仅显示USB设备,但可以移除过滤器)。
private void DeviceChangedEvent(object sender, EventArrivedEventArgs e)
{
    using (var moBase = (ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)
    {
        string oInterfaceType = moBase?.Properties["InterfaceType"]?.Value.ToString();
        string devicePNPId = moBase?.Properties["PNPDeviceID"]?.Value.ToString();
        string deviceDescription = moBase?.Properties["Caption"]?.Value.ToString();
        string eventMessage = $"{oInterfaceType}: {deviceDescription} ";

        switch (e.NewEvent.ClassPath.ClassName)
        {
            case "__InstanceDeletionEvent":
                eventMessage += " removed";
                break;
            case "__InstanceCreationEvent":
                eventMessage += "inserted";
                break;
            case "__InstanceModificationEvent":
            default:
                eventMessage += $" {e.NewEvent.ClassPath.ClassName}";
                break;
        }
        BeginInvoke(new Action(() => UpdateUI(eventMessage)));
    }
}

private void UpdateUI(string message)
{
   //Update the UI controls with information provided by the event
}

0

我该如何从Win32_DeviceChangeEvent中获取deviceId,以便请求Win32_PnPEntity? - Jeremi Sharkboy

0

您可以使用ORMi创建一个观察器,以便获取有关任何新设备的信息:

WMIHelper helper = new WMIHelper("root\\CimV2");

WMIWatcher watcher = new WMIWatcher("root\\CimV2", "SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_PnPEntity'");
watcher.WMIEventArrived += Watcher_WMIEventArrived;

然后你就可以监听这些事件:

private static void Watcher_WMIEventArrived(object sender, WMIEventArgs e)
{
    //DO YOUR WORK
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接