Использование WMI для определения того, какое устройство вызвало Win32_DeviceChangeEvent - PullRequest
10 голосов
/ 12 марта 2011

Я писал код, который обнаруживает добавление и удаление 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 *из Win32_PnPEntity "или какой-либо другой подобный запрос.НО, это очень неточный и громоздкий способ идентификации устройства, которое было удалено.Проблема в том, что я не могу точно сказать, какое устройство было добавлено, если я не кеширую весь список Win32_PnPEntity заранее и не выполняю действительно сумасшедшие сравнения / проверки.

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

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

1 Ответ

15 голосов
/ 16 марта 2011

Хорошо, после некоторого дальнейшего исследования и экспериментов я обнаружил, что мне нужно использовать другой запрос 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 в запросе выше), и вуаля! Я получаю конкретное устройство, которое было создано.Я хотел бы узнать, как мой оригинальный запрос «Выбрать * из Win32_DeviceChangeEvent» был бы вообще полезен для всех, поскольку никакой дополнительной информации после генерации уведомления о событии не предоставляется. В любом случае, этот новый запрос является значительно более чистым решением моей проблемы.WMI кажется довольно мощным, но найти правильный запрос для использования может быть сложно, и требует некоторых экспериментов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...