Powershell'无效查询'中的WMI查询

时间:2018-11-21 21:41:38

标签: powershell wmi get-wmiobject

尝试了解有关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 :(得分:1)

简短的回答...对属性进行筛选的能力取决于它是哪种WMI类以及属性类型是什么。

长答案...要在PowerShell中获取有关WMI类的更多信息,请使用Get-CimClass cmdlet。根据属性返回的数据,属性可以具有不同的值类型(即字符串,整数,布尔值)。在您的示例中,您尝试查询作为引用类型的属性“ Filter”。引用类型没有文字值,它只是对另一个类的实例的引用。您可以告诉一个引用属性,因为它显示了到另一个类的完整或部分路径(如在示例中看到的“ __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是“ Filter”属性所引用的,并且该类DOES具有简单的属性类型,因此我们可以从那里开始。您可以通过Name属性(一个字符串类型)查询__EventFilter。

有一些高级查询技术(ASSOCIATORS OFREFERENCES OF)可以帮助您通过基于引用的查询从__FilterToConsumerBinding中获取实例,但这是一个多步骤的过程。我建议您检出Microsoft Doc WQL上的Microsoft文档,但这是一个基本的两步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产生一个实例。由于枚举一个抽象类会返回许多不同的类,因此不会总是希望通过过滤来过滤相同的属性,因此除非您要对基类中包含的属性进行过滤,否则不允许进行过滤。要查看WMI类的基类是什么,可以使用此命令,并查看NTEventLogEventConsumer的基类是__EventConsumer。

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

通常,您可以使用查询SELECT * FROM __EventConsumer来枚举抽象类中的所有实例。这将显示所有实例,但是一旦您添加了一个WHERE子句,而该子句的属性不包含在基类中,则您将收到无效的查询,或者不返回任何实例。这就是为什么您可以直接查询NTEventLogEventConsumer而不是__EventConsumer的原因。

希望这会有所帮助。