Использование WMI для определения того, какое устройство вызвало Win32_DeviceChangeEvent

Я пишу код, который обнаруживает добавление и удаление USB-устройств, и я использовал следующий код WMI для регистрации уведомлений об изменении устройства:

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

Это код обработчика:

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

Это замечательно, и все это работает на любом USB-устройстве, которое я подключаю или удаляю из системы. Проблема, с которой я столкнулась, заключается в том, как определить устройство, специально вызвавшее события?

В других местах моей программы я сохраняю список подключенных в настоящее время устройств, которые меня больше всего интересуют, поэтому, если произойдет событие с удаленным устройством, я могу проверить этот список на WMI, используя "select * from Win32_PnPEntity", или какой-либо другой подобный запрос. НО, это очень неточный и громоздкий способ идентификации устройства, которое было удалено. Добавленная проблема заключается в том, что я не могу точно сказать, какое устройство было добавлено, если я не кэширую весь список Win32_PnPEntity раньше времени и делаю действительно сумасшедшие сравнения/проверки.

Я пропустил что-то очевидное здесь? Как связать события изменения устройства с конкретным устройством?

UPDATE: я до сих пор не нашел идеального решения этой проблемы, но то, что я делаю, это поддерживать список подключенных в настоящее время устройств (которые меня интересуют) в памяти, и каждый раз, когда событие (см. выше), я запрашиваю Win32_PnPEntity, чтобы проверить, все ли подключены устройства, которые я сохранил в списке подключенных устройств. Это субоптимальное решение, потому что кажется странным, что я не могу получить информацию об идентификаторе конкретного устройства из события, которое указывает "событие изменения устройства". Кажется ОЧЕНЬ странным, что эта информация недоступна. Вздох

Ответ 1

Хорошо, поэтому после некоторых дальнейших исследований и экспериментов я обнаружил, что мне нужно использовать другой запрос WMI для решения моей проблемы, связанный с событием смены устройства с определенным устройством. В этом случае мне нужно найти то, что, по-видимому, условно упоминается в WMI как "TargetInstance".

Итак, вместо этого я использовал следующий код запроса WMI

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

Итак, разница здесь в том, что __InstanceCreationEvent имеет свойство под названием "TargetInstance", которое ТОЧНО, что я искал. Я передал свойство TargetInstance в ManagementBaseObject (который имеет тип "Win32_PnPEntity" (в соответствии с предложением ISA в вышеприведенном запросе) и Voila! Я получаю определенное устройство, которое было создано.

Мне все же кажется, что мой первоначальный запрос "Select * from Win32_DeviceChangeEvent" был бы полезен для всех, поскольку дополнительная информация не предоставляется после уведомления об общем уведомлении о событиях. В любом случае, этот новый запрос представляет собой более чистое решение моей проблемы. WMI кажется довольно мощным, но поиск правильного запроса для использования может быть сложным и требует некоторых экспериментов.