首页 > 解决方案 > 无法使用 WMI API 在 .NET Framework 中实现 USB 检测

问题描述

private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
    ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
    foreach (var property in instance.Properties)
    {
        MessageBox.Show(property.Name + " = " + property.Value); // Dialog box appears as expected. 
        StatusMessage.Content = $"{property.Name} = {property.Value}";
    }
    StatusMessage.Content = "Removable Drive detected!"; //label content should be updated here, and for some reason it is not.
    bool isDriveRemoved = FindRemovableDrive(); //get the drive info
    if (isDriveRemoved || Count > 0)
    {
        Count = 0;
    }
    else
    {
        Count++;
    }
}

private void DeviceRemovedEvent(object sender, EventArrivedEventArgs e)
{
    ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
    foreach (var property in instance.Properties)
    {
        MessageBox.Show(property.Name + " = " + property.Value); // Dialog box appears as expected, but label is not updated. 
    }
    StatusMessage.Content = $"{property.Name} = {property.Value}";
    FileMenu.Items.Clear(); // the file menu should be getting cleared here. 
}

private void backgroundWorker1_DoWork(object sender, RoutedEventArgs e)
{
    WqlEventQuery insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");

    ManagementEventWatcher insertWatcher = new ManagementEventWatcher(insertQuery);
    insertWatcher.EventArrived += DeviceInsertedEvent;
    insertWatcher.Start();

    WqlEventQuery removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
    ManagementEventWatcher removeWatcher = new ManagementEventWatcher(removeQuery);
    removeWatcher.EventArrived += DeviceRemovedEvent;
    removeWatcher.Start();

    // Do something while waiting for events
    //Thread.Sleep(10000);
}

- 任何输入/解决方案将不胜感激。

谢谢你的时间,

迈克尔

标签: c#.netwpfwmi

解决方案


您可以使用 WMI 事件在发生硬件更改时收到通知,而不是定期扫描设备。

为即插即用事件启动监听器:

var wmiPath = new ManagementPath(@"root\cimv2");
var scope = new ManagementScope(wmiPath);
scope.Connect();
var instanceQuery = new WqlEventQuery("__InstanceOperationEvent",
                                        new TimeSpan(0, 0, 1),
                                        "TargetInstance isa \"Win32_PnPEntity\"");
wmiWatcher = new ManagementEventWatcher(scope, instanceQuery);
wmiWatcher.EventArrived += OnInstanceEvent;
wmiWatcher.Start();

事件处理程序:

private void OnInstanceEvent(object sender, EventArrivedEventArgs ea) {
  var eventType = (string)ea.NewEvent["__CLASS"];
  var targetWmiObj = ea.NewEvent["TargetInstance"] as ManagementBaseObject;
  var deviceId = (string)targetWmiObj["deviceId"];

 if (String.Equals("__InstanceCreationEvent", (string)ea.NewEvent["__CLASS"], StringComparison.Ordinal)) {
   if (/* Filter on the device id for what is interesting here*/) {
     // Handle relevant device arriving
    }
  }
}

NewEvent["__CLASS"]其他事件类型(包括设备移除)还有其他值。

PS。这是来自 WinForms 应用程序的(部分)代码,该应用程序监视正在插入的专用设备,然后从中下载/上传数据。所有工作都在线程池中完成:这里的一切都应该在 WPF 下工作。


推荐阅读