【问题标题】:How do I get information about recently connected USB device?如何获取有关最近连接的 USB 设备的信息?
【发布时间】:2019-01-21 16:50:31
【问题描述】:

当usb设备连接Win32_DeviceChangeEvent时我可以捕捉到

但只允许查看 3 个属性

class Win32_DeviceChangeEvent : __ExtrinsicEvent
{
  uint8  SECURITY_DESCRIPTOR[];
  uint64 TIME_CREATED;
  uint16 EventType;
};

但我不明白如何获取有关此设备的所有信息。具体来说,它的port and hub、VirtualHubAdress Name

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();
}

也许我可以像这样使用 smth 来做到这一点

[DllImport("UseFull.dll")] 
private IntpPtr GetAllinfo(params);

【问题讨论】:

    标签: c# .net windows wmi systemmanagement


    【解决方案1】:

    Win32_DeviceChangeEvent 仅报告发生的事件类型和事件时间(uint64,表示 1601 年 1 月 1 日之后的 100 纳秒间隔,UTC)。如果您还想知道什么是到达或被删除的,那就没有多大用处了。

    我建议改用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 类的管理对象。
    请参阅有关此处直接可用的属性的文档。

    e.NewEvent.ClassPath.ClassName 报告的感兴趣的__InstanceOperationEvent 派生类可以是:

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

    请注意,该事件是在辅助线程中引发的,我们需要BeginInvoke() UI 线程以使用新信息更新 UI。
    ▶ 这里应该避免Invoke(),因为它是同步的:它会阻塞处理程序直到方法完成。此外,在这种情况下,死锁并不是完全可能的。

    请参阅此处:Get serial number of USB storage device,该类提供了有关设备的大部分可用信息(信息被过滤以仅显示 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";
                    BeginInvoke(new Action(() => UpdateUI(eventMessage)));
                    break;
                case "__InstanceCreationEvent":
                    eventMessage += "inserted";
                    BeginInvoke(new Action(() => UpdateUI(eventMessage)));
                    break;
                case "__InstanceModificationEvent":
                default:
                    Console.WriteLine(e.NewEvent.ClassPath.ClassName);
                    break;
            }
        }
    }
    
    private void UpdateUI(string message)
    {
       //Update the UI controls with information provided by the event
    }
    

    【讨论】:

      【解决方案2】:

      您可以尝试使用 Win32_PnPEntity 来获取详细信息。 Win32_PnPEntity class

      【讨论】:

      • 我如何从 Win32_DeviceChangeEvent 获取例如 deviceId 以请求 Win32_PnPEntity ?
      【解决方案3】:

      您可以使用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
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-26
        • 1970-01-01
        • 2011-03-20
        相关资源
        最近更新 更多