about_WQL

简短说明

介绍可用于获取 Windows PowerShell 中的 WMI 对象的 WMI 查询语言 (WQL)。

长说明

WQL 是 Windows Management Instrumentation (WMI) 查询语言,它是用于从 WMI 获取信息的语言。

无需使用 WQL 在 Windows PowerShell 中执行 WMI 查询。 相反,可以使用 Get-WmiObject 的参数或 Get-CimInstance cmdlet。 WQL 查询比标准 Get-WmiObject 命令要快一些,并且当命令在数百个系统上运行时,性能的提高是显而易见的。 但是,请确保编写成功的 WQL 查询所花费的时间不会超过性能的改进。

使用 WQL 所需的基本 WQL 语句是 SELECTWHEREFROM

何时使用 WQL

使用 WMI(尤其是 WQL)时,不要忘记你也在使用 Windows PowerShell。 通常,如果 WQL 查询未按预期工作,则使用标准 Windows PowerShell 命令比调试 WQL 查询更容易。

除非要从带宽受限的远程系统返回大量数据,否则在可以使用 PowerShell cmdlet 完成相同操作的情况下,花费数小时尝试完善复杂的 WQL 查询是非常低效的选择。

使用 SELECT 语句

典型的 WMI 查询以 SELECT 语句开始,该语句可获取 WMI 类的所有属性或特定属性。 若要选择 WMI 类的所有属性,请使用星号 (*)。 FROM 关键字可指定 WMI 类。

SELECT 语句具有以下格式:

SELECT <property> FROM <WMI-class>

例如,以下 SELECT 语句从 Win32_Bios WMI 类的实例中选择所有属性 (*)。

SELECT * FROM Win32_Bios

注意

默认情况下,PowerShell 仅显示默认对象。 这些属性是在 Types.ps1xml 文件中定义的。 使用 Select-Object cmdlet 或 Format-* cmdlet 显示其他属性。

要选择 WMI 类的特定属性,请将属性名称放在关键字 SELECTFROM 之间。

以下查询仅从 Win32_Bios WMI 类中选择 BIOS 名称。 该命令将查询保存在 $queryName 变量中。

SELECT Name FROM Win32_Bios

若要选择多个属性,请使用逗号分隔属性名称。 以下 WMI 查询选择 Win32_Bios WMI 类的名称和版本。 该命令将查询保存在 $queryNameVersion 变量中。

SELECT name, version FROM Win32_Bios

使用 WQL 查询

在Windows PowerShell 命令中使用WQL 查询的方法有3 种。

  • 使用 Get-WmiObject cmdlet
  • 使用 Get-CimInstance cmdlet
  • 使用 [wmisearcher] 类型加速器。

使用 Get-WmiObject cmdlet

使用 WQL 查询的最基本方法是将其括在引号中(作为字符串),然后使用查询字符串作为 Get-WmiObject cmdlet 的 Query 参数的值,如以下示例所示。

Get-WmiObject -Query "SELECT * FROM Win32_Bios"
SMBIOSBIOSVersion : 8BET56WW (1.36 )
Manufacturer      : LENOVO
Name              : Default System BIOS
SerialNumber      : R9FPY3P
Version           : LENOVO - 1360

还可以将 WQL 语句保存在变量中,然后使用该变量作为查询参数的值,如以下命令所示。

$query = "SELECT * FROM Win32_Bios"
Get-WmiObject -Query $query

可以将任一格式与任何 WQL 语句一起使用。 以下命令使用 $queryName 变量中的查询来仅获取系统 BIOS 的 NameVersion 属性。

$queryNameVersion = "SELECT Name, Version FROM Win32_Bios"
Get-WmiObject -Query $queryNameVersion
__GENUS          : 2
__CLASS          : Win32_BIOS
__SUPERCLASS     :
__DYNASTY        :
__RELPATH        :
__PROPERTY_COUNT : 2
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
Name             : S03KT39A
Version          : LENOVO - 1270
PSComputerName   :

请记住,可以使用 Get-WmiObject cmdlet 的参数来获得相同的结果。 例如,以下命令还将获取 Win32_Bios WMI 类实例的 NameVersion 属性的值。

Get-WmiObject -Class Win32_Bios -Property Name, Version
__GENUS          : 2
__CLASS          : Win32_BIOS
__SUPERCLASS     :
__DYNASTY        :
__RELPATH        :
__PROPERTY_COUNT : 2
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
Name             : S03KT39A
Version          : LENOVO - 1270
PSComputerName   :

使用 Get-CimInstance cmdlet

从 Windows PowerShell 3.0 开始,可以使用 Get-CimInstance cmdlet 运行 WQL 查询。

Get-CimInstance 可获取符合 CIM 的类的实例,包括 WMI 类。 Windows PowerShell 3.0 中引入的 CIM cmdlet 执行与 WMI cmdlet 相同的任务。 CIM cmdlet 符合 WS 管理 (WSMan) 标准和通用信息模型 (CIM) 标准,这使得 cmdlet 能够使用相同的技术来管理 Windows 计算机和运行其他操作系统的计算机。

以下命令使用 Get-CimInstance cmdlet 运行 WQL 查询。

任何可与 Get-WmiObject 一起使用的 WQL 查询也可与 Get-CimInstance 一起使用。

Get-CimInstance -Query "SELECT * FROM Win32_Bios"
SMBIOSBIOSVersion : S03KT39A
Manufacturer      : LENOVO
Name              : S03KT39A
SerialNumber      : MJ0AETTX
Version           : LENOVO - 1270

Get-CimInstance 将返回 CimInstance 对象,而不是 Get-WmiObject 返回的 ManagementObject,但这些对象都非常相似。

PS> (Get-CimInstance -Query "SELECT * FROM Win32_Bios").GetType().FullName
Microsoft.Management.Infrastructure.CimInstance

PS> (Get-WmiObject -Query "SELECT * FROM Win32_Bios").GetType().FullName
System.Management.ManagementObject

使用 wmisearcher 类型加速器

[wmisearcher] 类型加速器将从 WQL 语句字符串创建 ManagementObjectSearcher 对象。 ManagementObjectSearcher 对象具有许多属性和方法,但最基本的方法是 Get 方法,它调用指定的 WMI 查询并返回结果对象。

通过使用 [wmisearcher],可以轻松访问 ManagementObjectSearcher .NET 类。 这样,便可以查询 WMI 并配置查询的执行方式。

要使用 [wmisearcher] 类型加速器:

  1. 将 WQL 字符串强制转换为 ManagementObjectSearcher 对象。
  2. 调用 ManagementObjectSearcher 对象的 Get 方法。

例如,以下命令将强制转换“全选”查询,将结果保存在 $bios 变量中,然后调用 $bios 变量中 ManagementObjectSearcher 对象的 Get() 方法。

$bios = [wmisearcher]"SELECT * FROM Win32_Bios"
$bios.Get()
SMBIOSBIOSVersion : 8BET56WW (1.36 )
Manufacturer      : LENOVO
Name              : Default System BIOS
SerialNumber      : R9FPY3P
Version           : LENOVO - 1360

可以使用 [wmisearcher] 类型加速器来强制转换查询或变量。 在以下示例中,使用 [wmisearcher] 类型加速器来强制转换变量。 结果是一样的。

[wmisearcher]$bios = "SELECT * FROM Win32_Bios"
$bios.Get()
SMBIOSBIOSVersion : S03KT39A
Manufacturer      : LENOVO
Name              : S03KT39A
SerialNumber      : MJ0AETTX
Version           : LENOVO - 1270

使用 [wmisearcher] 类型加速器时,它会将查询字符串更改为 ManagementObjectSearcher 对象,如以下命令所示。

$a = "SELECT * FROM Win32_Bios"
$a.GetType().FullName
System.String

$a = [wmisearcher]"SELECT * FROM Win32_Bios"
$a.GetType().FullName
System.Management.ManagementObjectSearcher

此命令格式适用于任何查询。 以下命令将获取 Win32_Bios WMI 类的 Name 属性的值。

$biosname = [wmisearcher]"Select Name from Win32_Bios"
$biosname.Get()
__GENUS          : 2
__CLASS          : Win32_BIOS
__SUPERCLASS     :
__DYNASTY        :
__RELPATH        :
__PROPERTY_COUNT : 1
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
Name             : S03KT39A
PSComputerName   :

使用基本 WQL WHERE 语句

WHERE 语句为 SELECT 语句返回的数据建立条件。

WHERE 语句具有以下格式:

WHERE <property> <operator> <value>

例如:

WHERE Name = 'Notepad.exe'

WHERE 语句与 SELECT 语句一起使用,如以下示例所示。

SELECT * FROM Win32_Process WHERE Name = 'Notepad.exe'

使用 WHERE 语句时,属性名称和值必须准确。

例如,以下命令将获取本地计算机上的记事本进程。

Get-WmiObject -Query "SELECT * FROM Win32_Process WHERE name='Notepad.exe'"

但是,以下命令失败,因为进程名称包含 .exe 文件扩展名。

Get-WmiObject -Query "SELECT * FROM Win32_Process WHERE name='Notepad'"

WHERE 语句比较运算符

以下运算符在 WQL WHERE 语句中有效。

Operator    Description
-----------------------
=           Equal
!=          Not equal
<>          Not equal
<           Less than
>           Greater than
<=          Less than or equal
>=          Greater than or equal
LIKE        Wildcard match
IS          Evaluates null
ISNOT       Evaluates not null
ISA         Evaluates a member of a WMI class

还有其他运算符,但这些运算符用于进行比较。

例如,以下查询从 Win32_Process 类中进程优先级大于或等于 11 的进程中选择 NamePriority 属性。 Get-WmiObject cmdlet 运行该查询。

$highPriority = "Select Name, Priority from Win32_Process " +
  "WHERE Priority >= 11"
Get-WmiObject -Query $highPriority

在 FILTER 参数中使用 WQL 运算符

WQL 运算符还可以用在 Get-WmiObjectGet-CimInstance cmdlet 的 Filter 参数的值中,以及这些 cmdlet 的 Query 参数的值中。

例如,以下命令可获取 ProcessID 值大于 1004 的最后五个进程的 NameProcessID 属性。 该命令使用 Filter 参数指定 ProcessID 条件。

$getWmiObjectSplat = @{
    Class = 'Win32_Process'
    Property = 'Name', 'ProcessID'
    Filter = "ProcessID >= 1004"
}
Get-WmiObject @getWmiObjectSplat |
    Sort-Object ProcessID |
    Select-Object Name, ProcessID -Last 5
Name                                 ProcessID
----                                 ---------
SROSVC.exe                                4220
WINWORD.EXE                               4664
TscHelp.exe                               4744
SnagIt32.exe                              4748
WmiPrvSE.exe                              5056

使用 LIKE 运算符

LIKE 运算符允许使用通配符来筛选 WQL 查询的结果。

Like Operator  Description
--------------------------------------------------
[]             Character in a range [a-f] or a set
               of characters [abcdef]. The items in
               a set don't need to be consecutive or
               listed in alphabetical order.

^              Character not in a range [^a-f] or
               not in a set [^abcdef]. The items in
               a set don't need to be consecutive or
               listed in alphabetical order.

%              A string of zero or more characters

_              One character.
(underscore)   NOTE: To use a literal underscore
               in a query string, enclose it in
               square brackets [_].

当使用不带任何通配符或范围运算符的 LIKE 运算符时,它的行为类似于等于运算符 (=),并且仅当对象与模式完全匹配时才返回对象。

可以将范围操作与百分比 (%) 通配符结合起来,以创建简单但功能强大的筛选器。

LIKE 运算符示例

示例 1:[<range>]

以下命令将启动记事本,然后搜索名称以“H”和“N”之间的字母(不区分大小写)开头的 Win32_Process 类的实例。

该查询应返回从 Hotepad.exeNotepad.exe 的任何进程。

Notepad   # Starts Notepad
$query = "SELECT * FROM Win32_Process WHERE Name LIKE '[H-N]otepad.exe'"
Get-WmiObject -Query $query | Select Name, ProcessID
Name                                ProcessID
----                                ---------
notepad.exe                              1740

示例 2:[<range>] 和 %

以下命令选择名称以 A 和 P 之间的字母开头(不区分大小写)的所有进程,后跟零个或多个字母的任意组合。

Get-WmiObject cmdlet 运行该查询,Select-Object cmdlet 将获取 NameProcessID 属性,Sort-Object 按名称的字母顺序对结果进行排序。

$query = "SELECT * FROM Win32_Process WHERE name LIKE '[A-P]%'"
Get-WmiObject -Query $query |
    Select-Object -Property Name, ProcessID |
    Sort-Object -Property Name

示例 3:不在范围中 (^)

以下命令将获取名称不以以下任何字母开头的进程:A、S、W、P、R、C、U、N

后跟零个或多个字母。

$query = "SELECT * FROM Win32_Process WHERE name LIKE '[^ASWPRCUN]%'"
Get-WmiObject -Query $query |
    Select-Object -Property Name, ProcessID |
    Sort-Object -Property Name

示例 4:任何字符 -- 或 none (%)

以下命令将获取名称以“calc”开头的进程。 百分比 (%) 符号是 WQL 通配符。 它等效于 PowerShell 中的星号 (*) 通配符。

$query = "SELECT * FROM Win32_Process WHERE Name LIKE 'calc%'"
Get-WmiObject -Query $query | Select-Object -Property Name, ProcessID
Name                               ProcessID
----                               ---------
calc.exe                                4424

示例 5:一个字符 (_)

以下命令将获取名称具有以下模式的进程:“c_lc.exe”,其中下划线字符代表任意一个字符。 此模式匹配 calc.execzlc.exec9lc.exe 中的任何名称,但不匹配其中“c”和“l”由多个字符分隔的名称。

$query = "SELECT * FROM Win32_Process WHERE Name LIKE 'c_lc.exe'"
Get-WmiObject -Query $query | Select-Object -Property Name, ProcessID
Name                                 ProcessID
----                                 ---------
calc.exe                                  4424

示例 6:完全匹配

以下命令将获取名为 WLIDSVC.exe 的进程。 即使查询使用关键字 LIKE,它也需要完全匹配,因为该值不包含任何通配符。

$query = "SELECT * FROM Win32_Process WHERE name LIKE 'WLIDSVC.exe'"
Get-WmiObject -Query $query | Select-Object -Property Name, ProcessID
```powershell

```output
Name                                 ProcessID
----                                 ---------
WLIDSVC.exe                                84

使用 OR 运算符

若要指定多个独立条件,请使用关键字 OR。 关键字 OR 出现在 WHERE 子句中。 它对两个(或多个)条件执行非独占 OR 运算,并返回满足任何条件的项目。

OR 运算符具有以下格式:

WHERE <property> <operator> <value> OR <property> <operator> <value> ...

例如,以下命令将获取 Win32_Process WMI 类的所有实例,但仅当进程名称为 winword.exeexcel.exe 时才返回它们。

$q = "SELECT * FROM Win32_Process WHERE Name='winword.exe'" +
  " OR Name='excel.exe'"
Get-WmiObject -Query $q

OR 语句可以用于两个以上的条件。 在以下查询中,OR 语句将获取 Winword.exeExcel.exePowershell.exe

$q = "SELECT * FROM Win32_Process WHERE Name='winword.exe'" +
  " OR Name='excel.exe' OR Name='powershell.exe'"

使用 AND 运算符

若要指定多个相关条件,请使用关键字 AND。 关键字 AND 出现在 WHERE 子句中。 它将返回满足所有条件的项目。

AND 运算符具有以下格式:

WHERE <property> <operator> <value> `AND` <property> <operator> <value> ...

例如,以下命令将获取名称为“Winword.exe”且进程 ID 为 6512 的进程。

请注意,这些命令使用 Get-CimInstance cmdlet。

$q = "SELECT * FROM Win32_Process WHERE Name = 'winword.exe' " +
  "AND ProcessID =6512"
Get-CimInstance -Query $q
ProcessId   Name             HandleCount      WorkingSetSize   VirtualSize
---------   ----             -----------      --------------   -----------
# 6512      WINWORD.EXE      768              117170176        633028608

所有运算符(包括 LIKE 运算符)都对 ORAND 运算符有效。 而且,可以将 ORAND 运算符组合在一个带有括号的查询中,告知 Windows PowerShell 先处理哪些子句。

此命令使用 Windows PowerShell 延续字符 (`) 将命令划分为两行。

搜索 NULL 值

在 WMI 中搜索空值具有挑战性,因为它可能会导致不可预测的结果。 Null 不是零,它不等效于空字符串。 有些 WMI 类属性已初始化,而其他属性则未初始化,因此搜索 null 可能不适用于所有属性。

要搜索 null 值,请使用包含“null”的 Is 运算符。

例如,以下命令将获取 IntallDate 属性为 null 值的进程。 这些命令会返回许多进程。

$q = "SELECT * FROM Win32_Process WHERE InstallDate is null"
Get-WmiObject -Query $q

相反,以下命令将获取 Description 属性具有 null 值的用户帐户。 此命令不会返回任何用户帐户,即使大多数用户帐户的 Description 属性没有任何值。

$q = "SELECT * FROM Win32_UserAccount WHERE Description is null"
Get-WmiObject -Query $q

若要查找没有 Description 属性值的用户帐户,请使用等于运算符获取空字符串。 若要表示空字符串,请使用两个连续的单引号。

$q = "SELECT * FROM Win32_UserAccount WHERE Description = '' "

使用 true 或 false

若要获取 WMI 对象属性中的布尔值,请使用 TrueFalse。 它们不区分大小写。

以下 WQL 查询仅返回来自加入域的计算机的本地用户帐户。

$q = "SELECT * FROM Win32_UserAccount WHERE LocalAccount = True"
Get-CimInstance -Query $q

若要查找域帐户,请使用值为 False,如以下示例所示。

$q = "SELECT * FROM Win32_UserAccount WHERE LocalAccount = False"
Get-CimInstance -Query $q

使用转义字符

WQL 使用反斜杠 (\) 作为其转义字符。 这与 Windows PowerShell 不同,后者使用反杆字符 (`)。

引号以及用于引号的字符通常需要转义,以免被误解。

若要查找名称包含单引号的用户,请使用反斜杠对单引号进行转义,如以下命令所示。

$q = "SELECT * FROM Win32_UserAccount WHERE Name = 'Tim O\'Brian'"
Get-CimInstance -Query $q
Name             Caption          AccountType      SID              Domain
----             -------          -----------      ---              ------
Tim O'Brian      FABRIKAM\TimO    512              S-1-5-21-1457... FABRIKAM

在某些情况下,反斜杠也需要转义。 例如,以下命令由于 Caption 值中的反斜杠而生成无效查询错误。

$q = "SELECT * FROM Win32_UserAccount WHERE Caption = 'Fabrikam\TimO'"
Get-CimInstance -Query $q
Get-CimInstance : Invalid query
At line:1 char:1
+ Get-CimInstance -Query $q
+ ~~~~~~~~~~~
  + CategoryInfo          : InvalidArgument: (:) [Get-CimInstance], CimExcep
  + FullyQualifiedErrorId : HRESULT 0x80041017,Microsoft.Management.Infrastr

若要转义反斜杠,请使用第二个反斜杠字符,如以下命令所示。

$q = "SELECT * FROM Win32_UserAccount WHERE Caption = 'Fabrikam\\TimO'"
Get-CimInstance -Query $q

另请参阅