Я знаю, что отвечаю на старый вопрос, но я только что прошел это же упражнение и узнал немного больше информации, которая, я думаю, внесет большой вклад в обсуждение и поможет всем, кто найдет этот вопрос ивидит, где существующих ответов не хватает.
Принятый ответ близок, и его можно исправить, используя комментарий Недко к нему.Более подробное понимание задействованных классов WMI помогает завершить картину.
Win32_USBHub
возвращает только USB Концентраторы .Оглядываясь назад, это кажется очевидным, но в приведенной выше дискуссии об этом не говорится.Он не включает в себя все возможные устройства USB, только те, которые могут (по крайней мере, в теории) выступать в качестве концентратора для дополнительных устройств.Он пропускает некоторые устройства, которые не являются концентраторами (в частности, части составных устройств).
Win32_PnPEntity
включает в себя все устройства USB и сотни других устройств, отличных от USB. Совет Рассела Гантмана по использованию предложения WHERE для поиска по номеру Win32_PnPEntity
для DeviceID, начинающегося с "USB%", для фильтрации списка полезен, но немного неполон;он пропускает устройства Bluetooth, некоторые принтеры / серверы печати, а также HID-совместимые мыши и клавиатуры.Я видел "USB \%", "USBSTOR \%", "USBPRINT \%", "BTH \%", "SWD \%" и "HID \%".Win32_PnPEntity
, однако, является хорошим «основным» справочником для поиска информации, когда вы обладаете PNPDeviceID из других источников.
То, что я нашел, было лучшим способом перечисления USB-устройств, это запрос Win32_USBControllerDevice
.Хотя он не дает подробной информации об устройствах, он полностью перечисляет ваши USB-устройства и дает вам пару Antecedent / Dependent PNPDeviceID
s для каждого USB-устройства (включая концентраторы, не-концентраторы и HID-совместимые устройства).) в вашей системе.Каждый зависимый, возвращенный из запроса, будет устройством USB.Antecedent будет тем Контроллером, которому он назначен, а один из контроллеров USB возвращается с помощью запроса Win32_USBController
.
В качестве бонуса представляется, что под капотом WMI при ответе на запрос Win32_USBControllerDevice
обходится Дерево устройств , поэтому порядок, в котором возвращаются эти результаты, может помочь определить родителя./ детские отношения.(Это не задокументировано и, таким образом, является лишь предположением; для получения окончательных результатов используйте API-интерфейс SetupDi CM_Get_Parent (или Child + Sibling ).) Как вариантПохоже, что в API SetupDi для всех устройств, перечисленных в Win32_USBHub
, их можно найти в реестре (в HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ + PNPDeviceID
), и у них будет параметр ParentIdPrefix
, который будет префиксом последнего поля в PNPDeviceID.его дочерних элементов, так что это также может быть использовано в сопоставлении с подстановочными знаками для фильтрации запроса Win32_PnPEntity
.
В моем приложении я сделал следующее:
- (необязательно) Запрошено
Win32_PnPEntity
и сохранил результаты в карте значения ключа (с PNPDeviceID в качестве ключа) для последующего извлечения.Это необязательно, если вы хотите выполнить отдельные запросы позже. - Запрос
Win32_USBControllerDevice
для получения окончательного списка USB-устройств в моей системе (всех зависимых элементов) и извлечения из них PNPDeviceID.Я пошел дальше, основываясь на порядке следования за деревом устройств, чтобы назначить устройства корневому концентратору (возвращено первое устройство, а не контроллер) и построил дерево на основе parentIdPrefix.Порядок, возвращаемый запросом, который соответствует перечислению дерева устройств через SetupDi, представляет собой каждый корневой концентратор (для которого Antecedent идентифицирует контроллер), за которым следует итерация устройств под ним, например, в моей системе: - Rootконцентратор первого контроллера
- корневой концентратор второго контроллера
- первый концентратор под корневым концентратором второго контроллера (имеет parentIdPrefix)
- первое составное устройство под первым концентратором под корневым концентратором второгоконтроллер (PNPDeviceID соответствует вышеуказанному ParentIdPrefix концентратора; имеет свой собственный ParentIdPrefix)
- HID Часть устройства составного устройства (PNPDeviceID соответствует вышеуказанному ParentIDPrefix составного устройства)
- Второе устройство под первымконцентратор под корневым концентратором второго контроллера
- HID Часть устройства составного устройства
- Второй концентратор под корневым концентратором второго контроллера
- Первое устройство под вторым концентратором под корневым концентраторомвторого контроллера
- Третий концентратор под корневым концентратором второго контроллера
- и т. д.
- Запрошено
Win32_USBController
.Это дало мне подробную информацию о PNPDeviceIDs моих контроллеров, которые находятся в верхней части дерева устройств (которые были Antecedents предыдущего запроса).Используя дерево, полученное на предыдущем шаге, рекурсивно итерируем его дочерние элементы (корневые концентраторы) и их дочерние элементы (другие концентраторы), а также их дочерние элементы (не-концентраторы и составные устройства) и их дочерние элементы и т. Д.* Полученные данные для каждого устройства в моем дереве, ссылаясь на карту, сохраненную в первом шаге.(При желании можно пропустить первый шаг и запросить Win32_PnPEntity
по отдельности, используя PNPDeviceId, чтобы получить информацию на этом шаге; возможно, соотношение между процессором и памятью определяет, какой порядок лучше.)
В итоге, Win32USBControllerDevice
Зависимости - это полный список USB-устройств в системе (кроме самих контроллеров, которые являются антецедентами в том же запросе), и путем перекрестной ссылки на эти пары PNPDeviceId
с информацией из реестра и из других упомянутых запросов можно построить детальную картину.