创建 WMI 脚本

可以使用脚本查看或操作通过 WMI 提供的任何信息。 脚本可以采用支持 Microsoft ActiveX 脚本托管的任何脚本语言编写,包括 Visual Basic Scripting Edition (VBScript) 、PowerShell 和 Perl。 Windows脚本主机 (WSH) 、Active Server Pages 和 Internet Explorer 都可以托管 WMI 脚本。

注意

WMI 当前支持的主要脚本语言是 PowerShell。 但是,WMI 还包含对 VBScript 和访问 WMI 脚本 API 的其他语言的可靠脚本支持正文。

 

WMI 脚本语言

WMI 支持的两种主要语言是 PowerShell 和 VBScript (,通过Windows脚本主机或 WSH) 。

  • PowerShell 的设计与 WMI 紧密集成。 因此,WMI 的大部分基础元素都内置于 WMI cmdlet 中: Get-WmiObjectSet-WmiInstanceInvoke-WmiMethodRemove-WmiObject。 下表描述了用于访问 WMI 信息的常规过程。 请注意,虽然其中大多数示例都使用 Get-WMIObject,但许多 PowerShell WMI cmdlet 具有相同的参数,如 -Class-Credentials。 因此,其中许多进程也适用于其他对象。 有关 PowerShell 和 WMI 的更深入讨论,请参阅使用 Get-WMiObject CmdletWindows PowerShell - WMI 连接

  • 相比之下,VBScript 显式调用 WMI 的脚本 API,如上所述。 其他语言(如 Perl)还可以使用 WMI 的脚本 API。 但是,出于本文档的目的,演示 WMI 脚本 API 的大多数示例都将使用 VBScript。 但是,当编程技术特定于 VBScript 时,将调用它。

    VBScript 基本上有两种不同的访问 WMI 方法。 第一个是使用 SWbemLocator 对象连接到 WMI。 或者,可以使用 GetObject 和名字对象。 名字对象是一个字符串,可以描述多个元素:凭据、模拟设置、要连接到的计算机、WMI 命名空间 ((即 WMI 存储) 对象组的常规位置),以及要检索哪些 WMI 对象。 下面的许多示例都描述了这两种技术。 有关详细信息,请参阅 构造名字对象字符串描述 WMI 对象的位置

    无论使用哪种技术连接到 WMI,都可能会从脚本 API 检索一个或多个对象。 最常见的是 SWbemObject,WMI 用于描述 WMI 对象。 或者,可以使用 SWbemServices 对象来描述 WMI 服务本身,也可以使用 SWbemObjectPath 对象来描述 WMI 对象的位置。 有关详细信息,请参阅 使用 SWbemObject脚本帮助程序对象的脚本

使用 WMI 和脚本语言,如何...

...连接到 WMI?

对于 VBScript 和 WMI 的脚本 API,请使用名字对象和对 GetObject 的调用检索 SWbemServices 对象。 或者,可以使用调用 SWbemLocator.ConnectServer 连接到服务器。 然后,可以使用该对象访问特定的 WMI 命名空间或 WMI 类实例。

对于 PowerShell,连接到 WMI 通常直接在 cmdlet 调用中完成;因此,无需执行其他步骤。

有关详细信息,请参阅 描述 WMI 对象的位置构造名字对象字符串以及 使用 VBScript 连接到 WMI

Set objLocator = CreateObject("WbemScripting.SWbemLocator")
Set objService = objLocator.ConnectServer(".", "root\cimv2")

' Second example: implicitly uses the local compuer (.) and default namespace ("root\cimv2")
Set objWMIService = GetObject("winmgmts:")

#Already has all the defaults set
get-WmiObject Win32_LogicalDisk

#Or, to be explicit,
get-WmiObject -class Win32_LogicalDisk -Computer "." -Namespace "root\cimv2" -Impersonation Impersonate

...从 WMI 检索信息?

对于 VBScript 和 WMI 脚本 API,请使用检索函数,例如 WbemServices.GetWbemServices.InstancesOf。 还可以将对象的类名放置在名字对象中检索,这可能会更高效。

对于 PowerShell,请使用 -Class 参数。 请注意,-Class 是默认参数;因此,无需显式声明它。

有关详细信息,请参阅 检索 WMI 类或实例数据

Set objLocator = CreateObject("WbemScripting.SWbemLocator")
Set objService = objLocator.ConnectServer(".", "root\cimv2")
Set colScheduledJobs = objService.InstancesOf("Win32_ScheduledJob")

' Second example
SSet Service = GetObject("WinMgmts:{impersonationLevel=impersonate}!Win32_Service=""ALERTER""")

#default - you don't actually need to use the -Class parameter
Get-WMIObject Win32_WmiSetting

#but you can if you want to
Get-WMIObject -Class Win32_WmiSetting

...创建 WMI 查询?

对于 VBScript 和 WMI 的脚本 API,请使用 SWbemServices.ExecQuery 方法。

对于 PowerShell,请使用 -Query 参数。 还可以使用 -Filter 参数进行筛选。

有关详细信息,请参阅 查询 WMI

strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colScheduledJobs = objWMIService.ExecQuery("Select * from Win32_ScheduledJob")
For Each objJob in colScheduledJobs
    Wscript.Echo "Job ID: " & objJob.JobId & "Command: " & objJob.Command & VBNewLine

Get-WmiObject -query "SELECT * FROM Win32_logicalDisk WHERE DeviceID = 'C:'"

#or

get-wmiObject -Class Win32_LogicalDisk -Filter "DeviceID = 'C:'"

...枚举 WMI 对象列表?

对于 VBScript 和 WMI 脚本 API,请使用 SWbemObjectSet 容器对象,该对象在脚本中被视为可以枚举的集合。 可以从 SWbemServices.InstancesOfSWbemServices.ExecQuery 调用检索SWbemObjectSet

PowerShell 可以像检索和处理任何其他对象一样检索和处理枚举;WMI 没有什么特别独特的。

有关详细信息,请参阅 访问集合

For Each Disk In GetObject("winmgmts:").InstancesOf ("CIM_LogicalDevice")

$logicalDevices = Get-WmiObject CIM_LogicalDevice
foreach ($device in $logicalDevices)
{
    $device.name
}

#or, to be more compact

Get-WmiObject cim_logicalDevice | ForEach-Object { $_.name }

...访问其他 WMI 命名空间?

对于 VBScript 和 WMI 的脚本 API,在名字对象中声明命名空间,或者可以在调用 SwbemLocator.ConnectServer 时显式声明命名空间。

对于 PowerShell,请使用 -Namespace 参数。 默认命名空间为“root\cimV2”;但是,许多较旧的类存储在“root\default”中。

若要查找给定 WMI 类的位置,请查看参考页。 或者,可以使用 get-WmiObject 手动浏览命名空间。

Set objLocator = CreateObject("WbemScripting.SWbemLocator")
Set objService = objLocator.ConnectServer(".", "root\cimv2")

' Second example
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & "." & "\root\cimv2")

Get-WmiObject -list * -Namespace root\default

#or, to retrieve all namespaces,
Get-WmiObject -Namespace root -Class __Namespace

...检索类的所有子实例?

对于直接使用 WMI 和 PowerShell 脚本 API 的语言,WMI 支持检索基类的子类。 因此,为了检索子实例,只需搜索父类。 以下示例搜索CIM_LogicalDisk,这是预安装的 WMI 类,该类表示基于Windows的计算机系统上的逻辑磁盘。 因此,搜索此父类还会返回Win32_LogicalDisk实例,这是Windows用于描述硬盘驱动器的实例。 有关详细信息,请参阅 通用信息模型。 WMI 提供此类预安装类的整个架构,使你能够访问和控制托管对象。 有关详细信息,请参阅 Win32 类WMI 类。。

For Each Disk In GetObject("winmgmts:").InstancesOf ("CIM_LogicalDisk")
  WScript.Echo "Instance:", Disk.Name
Get-WmiObject CIM_LogicalDisk | ForEach-Object { "Instance: " + $_.Name  }

...找到 WMI 对象?

对于 WMI 和 PowerShell 的脚本 API,WMI 使用命名空间、类名和键属性的组合来唯一标识给定的 WMI 实例。 一起称为 WMI 对象路径。 对于 VBScript, SWbemObject.Path_ 属性描述脚本 API 返回的任何给定对象的路径。 对于 PowerShell,每个 WMI 对象都将具有__PATH属性。 有关详细信息,请参阅 描述 WMI 对象的位置

除了命名空间和类名之外,WMI 对象还具有键属性,该属性唯一标识该实例与计算机上的其他实例相比。 例如, DeviceID 属性是 Win32_LogicalDisk 类的键属性。 有关详细信息,请参阅 托管对象格式 (MOF)

最后,相对路径只是路径的缩短形式,包括类名和键值。 在下面的示例中,路径可以是“\\computerName\root\cimv2:Win32_LogicalDisk.DeviceID=”D:“,而相对路径为”“Win32LogicalDisk.DeviceID=”D“。。

For Each Disk In GetObject("winmgmts:").InstancesOf ("CIM_LogicalDisk")
  WScript.Echo "Instance:", Disk.Path_.Relpath

'or to get the path
For Each Disk In GetObject("winmgmts:").InstancesOf ("CIM_LogicalDisk")
  WScript.Echo "Instance:", Disk.Path_
#retrieving the path
Get-WmiObject CIM_LogicalDisk | ForEach-Object { "Instance: " + $_.__PATH  }

#retrieving the relative path
Get-WmiObject CIM_LogicalDisk | ForEach-Object { "Instance: " + $_.__RELPATH  }

...在 WMI 中设置信息?

对于 VBScript 和用于 WMI 的脚本 API,请使用 SWbemObject.Put_ 方法。

对于 PowerShell,可以使用 Put 方法,也可以使用 Set-WmiInstance

有关详细信息,请参阅 修改实例属性

wbemCimtypeString = 8
Set objSWbemService = GetObject("Winmgmts:root\default")
Set objClass = objSWbemService.Get()
objClass.Path_.Class = "NewClass"

' Add a property
' String property
objClass.Properties_.add "PropertyName", wbemCimtypeString  
' Make the property a key property 
objClass.Properties_("PropertyName").Qualifiers_.add "key", true

' Write the new class to the root\default namespace in the repository
Set objClassPath = objClass.Put_
WScript.Echo objClassPath.Path

'Create an instance of the new class using SWbemObject.SpawnInstance
Set objNewInst = GetObject("Winmgmts:root\default:NewClass").Spawninstance_

objNewInst.PropertyName = "My Instance"

' Write the instance into the repository
Set objInstancePath = objNewInst.Put_
WScript.Echo objInstancePath.Path

$mySettings = get-WMIObject Win32_WmiSetting
$mySettings.LoggingLevel = 1
$mySettings.Put()

#or

Set-WMIInstance -class Win32_WMISetting -argument @{LoggingLevel=1}

...使用不同的凭据?

对于 VBScript 和 WMI 脚本 API,请使用 SWbemLocator.ConnectServer 方法中的 UserNamePassword 参数。

对于 PowerShell,请使用 -Credential 参数。

请注意,只能在远程系统上使用备用凭据。 有关详细信息,请参阅 保护脚本客户端

strComputer = "remoteComputerName" 
strDomain = "DOMAIN" 
Wscript.StdOut.Write "Please enter your user name:"
strUser = Wscript.StdIn.ReadLine 
Set objPassword = CreateObject("ScriptPW.Password")
Wscript.StdOut.Write "Please enter your password:"
strPassword = objPassword.GetPassword()
 
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objSWbemServices = objSWbemLocator.ConnectServer(strComputer, _
                                                     "Root\CIMv2", _
                                                     strUser, _
                                                     strPassword, _
                                                     "MS_409", _
                                                     "ntlmdomain:" + strDomain)
Set colSwbemObjectSet = objSWbemServices.ExecQuery("Select * From Win32_Process")
For Each objProcess in colSWbemObjectSet
    Wscript.Echo "Process Name: " & objProcess.Name 
Next

$Computer = "atl-dc-01"

Get-WmiObject -Namespace "root\cimv2" -Class Win32_Process -Credential FABRIKAM\administrator  `
-ComputerName $Computer

...访问远程计算机?

对于 VBScript 和 WMI 的脚本 API,请显式在名字对象中或调用 SWbemLocator.ConnectServer 中声明计算机的名称。 有关详细信息,请参阅 使用 VBScript 远程连接到 WMI

对于 PowerShell,请使用 -ComputerName 参数。 有关详细信息,请参阅 使用 PowerShell 远程连接到 WMI

Set objLocator = CreateObject("WbemScripting.SWbemLocator")
Set objService = objLocator.ConnectServer("myRemoteServerName", "root\cimv2")
Set colScheduledJobs = objService.ExecQuery("SELECT * FROM Win32_ScheduledJob")
For Each objJob in colScheduledJobs
    Wscript.Echo "Job ID: " & objJob.JobId & "Command: " & objJob.Command & VBNewLine

'example 2

strComputer = "myRemoteServerName"
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colScheduledJobs = objWMIService.ExecQuery("Select * from Win32_ScheduledJob")
For Each objJob in colScheduledJobs
    Wscript.Echo "Job ID: " & objJob.JobId & "Command: " & objJob.Command & VBNewLine

$Computer = "atl-dc-01"

Get-WmiObject -Namespace "root\cimv2" -Class Win32_logicalDisk -ComputerName $Computer

...设置身份验证和模拟级别?

对于 VBScript 和 WMI 脚本 API,请使用返回的服务器对象的 SWbemServices.Security_ 属性,或者在名字对象中设置相关值。

对于 PowerShell,请分别使用 -Authentication-Impersonation 参数。 有关详细信息,请参阅 保护脚本客户端

有关详细信息,请参阅 保护脚本客户端

' First example
Set Service = GetObject("WinMgmts:{impersonationLevel=impersonate}!Win32_Service=""ALERTER""")

' Second example
Set Locator = CreateObject("WbemScripting.SWbemLocator")
Set Service = Locator.ConnectServer       
service.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate  
Set objinstance = Service.Get("Win32_Service=""ALERTER""")

$Computer = "atl-dc-01"

Get-WmiObject -Namespace "root\cimv2" -Class Win32_Process -Impersonation Impersonate `
 -Authentication PacketIntegrity -Credential FABRIKAM\administrator -ComputerName $Computer

...处理 WMI 中的错误?

对于 WMI 的脚本 API,提供程序可能提供 SWbemLastError 对象来提供有关错误的详细信息。

特别是在 VBScript 中,使用本机 Err 对象也支持错误处理。 还可以访问 SWbemLastError对象,如上文所述。 有关详细信息,请参阅 检索错误代码

对于 PowerShell,可以使用标准的 PowerShell 错误处理技术。 有关详细信息,请参阅 PowerShell 中的错误处理简介

'using Err
On Error Resume Next
Set objProcess = GetObject("winmgmts:root\cimv2:Win32_Process.Handle='one'")
Wscript.Echo Err.Number

'using SWbemLastError

On Error Resume Next
Set obj = GetObject("winmgmts:root\cimv2:Win32_Process.Handle='one'")
Set LastError = createobject("wbemscripting.swbemlasterror")
Wscript.Echo "Operation = " & LastError.operation & VBCRLF & "ParameterInfo = " _
            & LastError.ParameterInfo & VBCRLF & "ProviderName = " & LastError.ProviderName