Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
535 views
in Technique[技术] by (71.8m points)

c# - Using WMI to identify which device caused a Win32_DeviceChangeEvent

I have been writing some code that detects add and removal of USB devices, and I've used the following WMI code to register for device change notifications:

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

This is the handler code:

void DeviceChangeEventReceived(object sender, EventArrivedEventArgs e)
{
   foreach (PropertyData pd in e.NewEvent.Properties)
   {
      Log.Debug("" + pd.Name + ":" + pd.Value + "" + pd.Value.GetType());
   }
}

This is great and all, it works for any USB device I plug in or remove from the system. The problem that I'm having is, how do I identify the the device specifically that caused the events?

Elsewhere in my program, I'm keeping a list of currently connected devices that I'm most interested in, so if a device-removed event comes through, I can check that list against WMI using "select * from Win32_PnPEntity" or some other similar query. BUT, this is a very inaccurate and cumbersome way of identifying the device that was removed. The added problem is, I have no way of accurately telling what device was added, unless I cache the entire list of Win32_PnPEntity ahead of time, and do really crazy comparisons/validations.

Am I missing something obvious here? How do I associate the device change events to a specific device?

UPDATE: I still haven't come up with an ideal solution to this problem, but what I am doing is maintaining a list of currently connected devices (that I'm interested in) in memory, and every time an event is handled (see above), I query the Win32_PnPEntity to see if the devices I have stored in my connected device list are still connected. This is a sub-optimal solution, because it just seems weird that I can't get any specific device identification information from the event that indicates "device change event". Seems VERY strange, that this info is unavailable. sigh

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Okay, so after some further investigation and experimenting, I've discovered that I need to use a different WMI query in order to solve my problem, which is to associate a device change event with a specific device. In this case, I need to find what seems to be conventionally referred to in WMI as "TargetInstance".

So, I used the following WMI query code instead

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

So the difference here is, that the __InstanceCreationEvent has a property called "TargetInstance", which is EXACTLY what I was looking for. I cast the TargetInstance property to a ManagementBaseObject (which is of type "Win32_PnPEntity" (per the ISA clause in the query above), and Voila! I get the specific device that was created.

It still sort of baffles me as to how my original query "Select * from Win32_DeviceChangeEvent" would be useful to anyone at all, since there's no additional information provided after a generic event notification is fired. Either way, this new query a significantly cleaner solution to the my problem. WMI seems pretty powerful, but finding the correct query to use can be tricky, and requires some experimenting.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...