Запросы WMI в powershell «Неверный запрос»

Попытка узнать больше о командах WMI и powershell (noob).

Выполнение этого:

Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding

Получает меня это (хорошо):

__GENUS                 : 2
__CLASS                 : __FilterToConsumerBinding
__SUPERCLASS            : __IndicationRelated
__DYNASTY               : __SystemClass
__RELPATH               : __FilterToConsumerBinding.Consumer="NTEventLogEventConsumer.Name=\"SCM Event Log Consumer\"",Filter="__EventFilter.Name=\"SCM Event Log Filter\""
__PROPERTY_COUNT        : 7
__DERIVATION            : {__IndicationRelated, __SystemClass}
__SERVER                : COMPUTERNAME
__NAMESPACE             : ROOT\Subscription
__PATH                  : \COMPUTERNAME\ROOT\Subscription:__FilterToConsumerBinding.Consumer="NTEventLogEventConsumer.Name=\"SCM Event Log Consumer\"",Filter="__EventFilter.Name=\"SCM Event Log Filter\""
Consumer                : NTEventLogEventConsumer.Name="SCM Event Log Consumer"
CreatorSID              : {1, 2, 0, 0...}
DeliverSynchronously    : False
DeliveryQoS             : 
Filter                  : __EventFilter.Name="SCM Event Log Filter"
MaintainSecurityContext : False
SlowDownProviders       : False
PSComputerName          : COMPUTERNAME

Почему этот запрос дает мне тот же результат, что и выше:

Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding -Filter "__PATH LIKE '%SCM%'"

Но этот, ищущий текст в «Фильтре»:

Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding -Filter "Filter LIKE '%SCM%'"`

дает мне недопустимую ошибку запроса

    Get-WMIObject : Invalid query "select * from __FilterToConsumerBinding where Filter LIKE '%SCM%'"
    At line:1 char:1
    + Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerB ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (:) [Get-WmiObject], ManagementException
        + FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

Я не понимаю, почему один и тот же запрос не работает с обоими объектами? Спасибо!

Не работает и с EventConsumer, но работает с EventFilter!

Get-WMIObject -Namespace root\Subscription -Class __EventFilter -Filter "Name LIKE '%SCM%'"


__GENUS          : 2
__CLASS          : __EventFilter
__SUPERCLASS     : __IndicationRelated
__DYNASTY        : __SystemClass
__RELPATH        : __EventFilter.Name="SCM Event Log Filter"
__PROPERTY_COUNT : 6
__DERIVATION     : {__IndicationRelated, __SystemClass}
__SERVER         : COMPUTERNAME
__NAMESPACE      : ROOT\Subscription
__PATH           : \\COMPUTERNAME\ROOT\Subscription:__EventFilter.Name="SCM Event Log Filter"
CreatorSID       : {1, 2, 0, 0...}
EventAccess      : 
EventNamespace   : root\cimv2
Name             : SCM Event Log Filter
Query            : select * from MSFT_SCMEventLogEvent
QueryLanguage    : WQL
PSComputerName   : COMPUTERNAME

person JohnRain    schedule 21.11.2018    source источник
comment
Я подозреваю, потому что Filter генерируется powershell для этого объекта, и на самом деле вы хотите что-то вроде Name LIKE '%SCM%'   -  person Maximilian Burszley    schedule 22.11.2018
comment
Спасибо за ответ @TheIncorrigible1, который я пытался отредактировать выше, это позволило мне запросить фильтр свойств.   -  person JohnRain    schedule 22.11.2018
comment
Нет, где в вашем вопросе вы запрашиваете свойство Filter в классе \\.\root\Subscription:__FilterToConsumerBinding.   -  person Maximilian Burszley    schedule 22.11.2018
comment
Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding | Выберите Фильтр (это было не так?)   -  person JohnRain    schedule 22.11.2018
comment
Select-Object -Property Filter не является запросом. Это просто выбор свойства и превращение его в pscustomobject. Как я уже сказал, powershell создает это свойство, чтобы вы были хорошими.   -  person Maximilian Burszley    schedule 22.11.2018
comment
А, Ок, понял. Да, имя LIKE '%SCM%' не работает с привязкой FilterToConsumerBinding, НО работает с EventFilter... еще больше запутанно, ха!   -  person JohnRain    schedule 22.11.2018


Ответы (1)


Краткий ответ... ваша способность фильтровать свойство зависит от того, какой это класс WMI и какие типы свойств.

Подробный ответ... Чтобы получить дополнительные сведения о классе WMI в PowerShell, используйте командлет Get-CimClass. Свойства могут иметь различные типы значений в зависимости от данных, которые они возвращают (т.е. String, Integers, Boolean). В вашем примере вы пытаетесь запросить свойство «Фильтр», которое является ссылочным типом. Ссылочный тип не имеет буквального значения, это просто ссылка на экземпляр из другого класса. Вы можете указать ссылочное свойство, потому что оно показывает полный или частичный путь к другому классу (как вы видели в вашем примере, на «__EventFilter» ссылались. Вы также можете получить информацию о типе свойства из этой команды powershell:

Get-CimClass -Namespace "root\Subscription" -Class __FilterToConsumerBinding | Select-Object -ExpandProperty CimClassProperties | Where-Object {$_.Name -eq 'Filter'}

Свойства ссылочного типа отображаются в классах WMI, у которых квалификатор класса "Association" имеет значение true. Квалификаторы класса — это свойства самого класса, определяющие его поведение. Вы можете увидеть все квалификаторы класса, используя эту команду.

Get-CimClass -Namespace "root\Subscription" -Class __FilterToConsumerBinding | Select-Object -ExpandProperty CimClassQualifiers

К сожалению, поскольку WQL является языком запросов, вы не можете фильтровать экземпляры класса на основе свойств со ссылочным типом, используя предложение WHERE. Вы можете использовать только простые типы, такие как строка, целое число или свойство встроенного объекта (хотя встроенные объекты встречаются крайне редко).

Поскольку класс __EventFilter является тем, на что ссылается свойство «Фильтр», и этот класс имеет простые типы свойств, мы можем начать с него. Вы можете запросить __EventFilter по свойству Name, которое является строковым типом, без каких-либо проблем.

Существуют некоторые расширенные методы запросов (ASSOCIATORS OF и REFERENCES OF), которые могут помочь вам получить экземпляр из __FilterToConsumerBinding с запросами на основе ссылок, но это многоэтапный процесс. Я бы порекомендовал проверить Microsoft Doc на нем Microsoft Doc WQL, но вот базовая двухшаговая команда PowerShell, которая сначала получит имя экземпляра, на который ссылаются, а затем любые экземпляры, которые на него ссылаются.

$InstanceName = (Get-WmiObject -Namespace "ROOT\subscription" -Query "SELECT * FROM __EventFilter WHERE Name LIKE '%SCM%'").Name
Get-WmiObject -Namespace "ROOT\subscription" -Query "REFERENCES OF {__EventFilter.Name='$InstanceName'}"

Поскольку REFERENCES OF будет выполнять поиск по всему пространству имен, вы можете сузить результаты до определенного класса, добавив предложение WHERE и назвав ResultClass в качестве целевого класса. Пересмотренная вторая строка вашей команды теперь будет

Get-WmiObject -Namespace "ROOT\subscription" -Query "REFERENCES OF {__EventFilter.Name='$InstanceName'} WHERE ResultClass = __FilterToConsumerBinding"

Это должно вернуть экземпляр, который вы ищете, только из __FilterToConsumerBinding. (*Обратите внимание, что имя класса не заключено в кавычки. Использование двойных или одинарных кавычек приведет к ошибке недопустимого запроса.

Чтобы ответить на ваш вопрос о классе __EventConsumer, это вызывает еще одну концепцию WMI, называемую абстрактными классами. Я не буду вдаваться в подробности, но абстрактный класс по сути является базовым классом (отправной точкой для других классов), который могут наследовать другие классы. Однако, в отличие от стандартных базовых классов, абстрактные классы не могут иметь собственных экземпляров. Вы можете узнать, является ли класс абстрактным, получив квалификаторы класса __EventConsumer. Вы заметите, что если вы запустите приведенную ниже команду, вы увидите, что она имеет квалификатор класса "abstract".

Get-CimClass -Namespace "root\Subscription" -Class __EventConsumer | Select-Object -ExpandProperty CimClassQualifiers

Поскольку абстрактный класс сам не может содержать никаких экземпляров, если вы перечислите его, он вернет экземпляры для всех классов, которые используют его в качестве базового класса. В вашем примере __EventConsumer фактически дает экземпляр из NTEventLogEventConsumer. Поскольку перечисление абстрактного класса возвращает несколько разных классов, не всегда будет обещание одних и тех же свойств для фильтрации, поэтому фильтрация не разрешена, если только вы не фильтруете свойство, содержащееся в базовом классе. Чтобы узнать, что такое базовый класс класса WMI, вы можете использовать эту команду и увидеть, что базовым классом для NTEventLogEventConsumer является __EventConsumer.

Get-CimClass -Namespace "root\Subscription" -Class NTEventLogEventConsumer | Select-Object -ExpandProperty CimSuperClassName

Обычно вы можете перечислить все экземпляры абстрактного класса, используя запрос SELECT * FROM __EventConsumer. Это покажет все экземпляры, но как только вы добавите предложение WHERE со свойством, не включенным в базовый класс, вы либо получите неверный запрос, либо экземпляры не будут возвращены. По этой причине вы можете напрямую запрашивать NTEventLogEventConsumer, но не __EventConsumer.

Надеюсь это поможет.

person Paul G    schedule 22.11.2018
comment
Святая корова, я читаю и перечитываю это, чтобы попытаться понять и понять! Я люблю объяснения с ответами, для меня в этом вся цель stackoverflow. Спасибо, я потрачу следующую неделю или около того, работая над вашим ответом! - person JohnRain; 26.11.2018
comment
Обратите внимание, что свойство PnPClass не существует в Windows. 7. Вместо этого вы должны использовать ClassGuid. См. Поддерживаемые классы USB-устройств для идентификаторов GUID. - person Chiramisu; 27.05.2021