WMI-запросы в PowerShell «Неверный запрос» - PullRequest
0 голосов
/ 22 ноября 2018

Попытка узнать больше о командах 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

1 Ответ

0 голосов
/ 22 ноября 2018

Короткий ответ ... Ваша способность фильтровать свойство зависит от того, какой это класс 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 - это то, на что ссылается свойство «Фильтр», и этот класс DOES имеет простые типы свойств, с которых мы можем начинать.__EventFilter от tСвойство 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. Если вы выполните команду ниже, вы увидите, что у нее есть «абстрактный» классификатор класса.

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

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

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

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

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

...