0
  • I am trying to implement the code from the following link: Detecting USB drive insertion and removal using windows service and c#
  • I think the issue I am having is that my main UI thread isn't being notified by the background thread when the device is inserted or removed. I verified this by not being able to update the content of a label in my user control.
  • I have included my source code below:
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);
}

-Any input/solutions would be greatly appreciated.

Thanks for your time,

Michael

Richard
  • 106,783
  • 21
  • 203
  • 265
  • I apologize for the formatting of the source code, I am new to posting questions on here. – MichaelJordan Mar 04 '21 at 20:48
  • You would be better off using WMI events to detect device additions/removals. And the either filtering the event (need to know something like the device id) or then enumerating. (Can't currently do an example: source code is not to hand.) – Richard Mar 04 '21 at 21:02

1 Answers1

0

Rather than regularly scanning devices you can use a WMI Events to be notified when there is a hardware change.

Starting a listener for plug & play events:

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

The event handler:

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
    }
  }
}

There are other values of NewEvent["__CLASS"] for other event types (including device removal).

PS. This is (partial) code from a WinForms app that monitored for a specialised device being plagged in and then downloaded/uploaded data from it. All the work was done in the thread pool: everything here should just work under WPF.

Richard
  • 106,783
  • 21
  • 203
  • 265
  • Thanks Richard, I will try this out. – MichaelJordan Mar 05 '21 at 14:18
  • Hi Richard, I am not able to remove the error that IntelliSense is giving me for wmiWatcher. I have placed the code you added within a user control as seen below: – MichaelJordan Mar 05 '21 at 19:06
  • It says that wmiWatcher doesn't exist in the current context. Any ideas on how to fix this? – MichaelJordan Mar 05 '21 at 19:14
  • Nevermind, I fixed it. I added private ManagementEventWatcher wmiWatcher; at the class level. – MichaelJordan Mar 05 '21 at 19:17
  • I was able to get the MessageBox to appear when removing usb, but I'm still not able to clear all items from the file menu (ListBox) using "FileMenu.Items.Clear();". I am calling ClearFileMenu(); from within the OnInstanceEvent method that Richard provided. Any ideas on where to go from here? I just want to clear the listBox when the drive is removed and repopulate it when a drive is inserted. I am not able to do that currently. – MichaelJordan Mar 05 '21 at 20:08
  • @MichaelJordan anything about UI is a different question entirely. I suggest you focus on one thing at a time. – Richard Mar 05 '21 at 20:56
  • Ok, thank you for the feedback Richard. I think I have a good idea on where to go from here. I appreciate your help. – MichaelJordan Mar 08 '21 at 14:01
  • can you take a look at my recent post if you get a chance. Thank you. https://stackoverflow.com/questions/66693210/how-to-close-the-current-open-user-control-pop-up-from-a-background-user-contr – MichaelJordan Mar 18 '21 at 14:50