【问题标题】:WMI queries in powershell 'Invalid query'Powershell中的WMI查询“无效查询”
【发布时间】:2018-11-21 21:41:37
【问题描述】:

尝试了解有关 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%'"

但是这个,在 'Filter' 中寻找文字:

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

【问题讨论】:

  • 我怀疑是因为 Filter 是由 powershell 在该对象上生成的,而您真正想要的是 Name LIKE '%SCM%'
  • 感谢@TheIncorrigible1 的回答,我尝试在上面进行编辑,它确实让我查询了属性过滤器。
  • 不知道您在哪里查询Filter 类的Filter 属性。
  • Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding |选择过滤器(不对吗?)
  • Select-Object -Property Filter 不是查询。它只是选择一个属性并将其转换为pscustomobject。就像我说的,powershell 为你创造了这个属性。

标签: powershell wmi get-wmiobject


【解决方案1】:

简短的回答...您过滤属性的能力取决于它是什么类型的 WMI 类以及属性类型是什么。

长答案...要获取有关 PowerShell 中 WMI 类的更多信息,请使用 Get-CimClass cmdlet。属性可以根据它们返回的数据(即字符串、整数、布尔值)具有不同的值类型。在您的示例中,您正在尝试查询作为引用类型的属性“过滤器”。引用类型没有文字值,它只是对另一个类的实例的引用。您可以告诉引用属性,因为它显示了另一个类的完整或部分路径(正如您在示例中看到的“__EventFilter”被引用。您还可以从此 powershell 命令获取属性类型信息:

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

引用类型属性显示在将名为“关联”的类限定符设置为 true 的 WMI 类上。类限定符是类本身的属性,它决定类的行为方式。您可以使用此命令查看所有类限定符。

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

不幸的是,由于 WQL 是一种查询语言,因此您无法使用 WHERE 子句根据具有引用类型的属性过滤类的实例。您只能使用简单类型,例如字符串、整数或嵌入对象的属性(但嵌入对象极为罕见)。

由于类 __EventFilter 是由“Filter”属性引用的,并且该类确实具有简单的属性类型,我们可以从那里开始。可以通过Name属性查询__EventFilter,它是字符串类型,没有任何问题。

有一些高级查询技术(ASSOCIATORS OFREFERENCES 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 产生一个实例。由于枚举抽象类会返回许多不同的类,因此并不总是承诺要过滤相同的属性,因此除非您对包含在基类中的属性进行过滤,否则不允许过滤。要查看 WMI 类的基类是什么,可以使用此命令并查看 NTEventLogEventConsumer 的基类是 __EventConsumer。

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

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

希望这会有所帮助。

【讨论】:

  • 天哪,我正在阅读并重新阅读此内容以尝试掌握并理解它!我喜欢用答案来解释,对我来说这就是 stackoverflow 的全部目的。谢谢,我将在接下来的一周左右为您解答!
  • 请注意,PnPClass 属性在 Windows 7 中不存在。您必须改用ClassGuid。有关 GUID,请参阅 Supported USB Device Classes
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多