创建 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 时,将会调用该 API。

    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,通常直接在 cmdlet 调用中完成对 WMI 的连接;因此,无需执行其他步骤。

有关详细信息,请参阅描述 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 的脚本 API 和 PowerShell 的语言,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 的脚本 API 和 PowerShell,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 方法中使用 UserName 和 Password 参数。

对于 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