Использование 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 и не сделаю действительно сумасшедшие сравнения / проверки.

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

ОБНОВЛЕНИЕ: я все еще не нашел идеального решения этой проблемы, но я делаю, чтобы поддерживать список подключенных в данный момент устройств (которые меня интересуют) в памяти, и каждый раз, когда событие обрабатывается (см. выше), я запрашиваю 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 в запросе выше), и вуаля! Я получаю конкретное устройство, которое было создано.

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

Другие вопросы по тегам