Como criar um script do WMI

Você pode exibir ou manipular qualquer informação disponibilizada por meio do WMI usando scripts. Os scripts podem ser escritos em qualquer linguagem de script que dê suporte à hospedagem de script do Microsoft ActiveX, incluindo Visual Basic Scripting Edition (VBScript), PowerShell e Perl. O WSH (Host de Scripts do Windows), o Active Server Pages e o Internet Explorer podem hospedar scripts WMI.

Observação

A principal linguagem de script atualmente compatível com o WMI é o PowerShell. No entanto, o WMI também contém um corpo robusto de suporte de script para VBScript e outras linguagens que acessam a API de Script para WMI.

 

Linguagens de script do WMI

As duas principais linguagens compatíveis com o WMI são PowerShell e VBScript (por meio do Host de Scripts do Windows ou WSH).

  • O PowerShell foi projetado tendo uma integração estreita com o WMI em mente. Assim, grande parte dos elementos subjacentes do WMI são incorporados aos cmdlets do WMI: Get-WmiObject, Set-WmiInstance, Invoke-WmiMethod e Remove-WmiObject. A tabela a seguir descreve os processos gerais usados para acessar informações do WMI. Observe que, embora a maioria desses exemplos use o Get-WMIObject, muitos dos cmdlets do WMI no PowerShell têm os mesmos parâmetros, como -Class ou -Credentials. Portanto, muitos desses processos também funcionam em outros objetos. Para ver uma discussão mais detalhada sobre o PowerShell e o WMI, consulte Usando o cmdlet Get-WMiObject e Windows PowerShell – a conexão com o WMI.

  • O VBScript, por outro lado, faz chamadas explícitas para a API de Script para WMI, conforme mencionado acima. Outras linguagens, como Perl, também podem usar a API de script para WMI. No entanto, nesta documentação, a maioria dos exemplos que demonstram a API de script para WMI usará a VBScript. Mas se houver uma técnica de programação específica da VBScript, ela será destacada.

    A VBScript tem essencialmente duas maneiras distintas de acessar o WMI. A primeira é usar um objeto SWbemLocator para se conectar ao WMI. Como alternativa, você pode usar GetObject e um moniker. Um moniker é uma cadeia de caracteres que pode descrever vários elementos: suas credenciais, configurações de representação, a qual computador você deseja se conectar, o namespace do WMI (ou seja, o local geral em que o WMI armazena grupos de objetos) e qual objeto do WMI você deseja recuperar. Muitos dos exemplos abaixo descrevem ambas as técnicas. Para obter mais informações, consulte Construir uma cadeia de caracteres Moniker e Descrever o local de um objeto do WMI.

    Independentemente da técnica usada para se conectar ao WMI, você provavelmente recuperará um ou mais objetos da API de Script. O mais comum é o SWbemObject, que o WMI usa para descrever um objeto do WMI. Como alternativa, você pode usar um objeto SWbemServices para descrever o próprio serviço do WMI ou um objeto SWbemObjectPath para descrever o local de um objeto do WMI. Para obter mais informações, consulte Criar scripts com SWbemObject e Criar script de objetos auxiliares.

Com o WMI e uma linguagem de script, como faço para...

...conectar ao WMI?

Para VBScript e a API de Script para WMI, recupere um objeto SWbemServices com um moniker e uma chamada para GetObject. Como alternativa, você pode se conectar ao servidor com uma chamada para SWbemLocator.ConnectServer. Em seguida, você pode usar o objeto para acessar um namespace do WMI específico ou uma instância de classe do WMI.

No PowerShell, a conexão com o WMI geralmente é feita diretamente na chamada do cmdlet; assim, nenhuma etapa adicional é necessária.

Para obter mais informações, consulte Descrever o local de um objeto do WMI, Construir uma cadeia de caracteres Moniker e Conectar-se ao WMI com VBScript.

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

... recuperar informações do WMI?

Na VBScript e na API de Script para WMI, use uma função de recuperação, como WbemServices.Get ou WbemServices.InstancesOf. Você também pode colocar o nome de classe do objeto a ser recuperado em um moniker, o que pode ser mais eficiente.

No PowerShell, use o parâmetro -Class. Observe que -Class é o parâmetro padrão; dessa forma, você não precisa declará-lo explicitamente.

Para obter mais informações, consulte Recuperar dados de classe ou de instância do 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

... criar uma consulta do WMI?

Na VBScript e na API de Script para WMI, use o método SWbemServices.ExecQuery.

No PowerShell, use o parâmetro -Query. Você também pode filtrar usando o parâmetro -Filter.

Para obter mais informações, confira Consultar o 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:'"

... enumerar por meio de uma lista de objetos do WMI?

Na VBScript e na API de Script para WMI, use o objeto de contêiner SWbemObjectSet, que é tratado no script como uma coleção que pode ser enumerada. Você pode recuperar um SWbemObjectSet em uma chamada de SWbemServices.InstancesOf ou SWbemServices.ExecQuery.

O PowerShell pode recuperar e manipular enumerações como faria com qualquer outro objeto; não há nada muito diferente no WMI.

Para obter mais informações, consulte Acessar uma coleção.

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 }

... acessar um namespace do WMI diferente?

Na VBScript e na API de Script para WMI, declare o namespace no moniker, mas você também pode declarar explicitamente o namespace na chamada para SwbemLocator.ConnectServer.

No PowerShell, use o parâmetro -Namespace. O namespace padrão é "root\cimV2"; no entanto, muitas classes mais antigas são armazenadas em "root\default".

Para encontrar o local de uma determinada classe do WMI, examine a página de referência. Como alternativa, você pode explorar manualmente um namespace usando 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

... recuperar todas as instâncias filho de uma classe?

Nas linguagens que usam diretamente a API de Script para WMI e o PowerShell, o WMI dá suporte à recuperação das classes filho de uma classe base. Dessa forma, para recuperar as instâncias filho, você precisa pesquisar apenas a classe pai. O exemplo a seguir pesquisa CIM_LogicalDisk, que é uma classe do WMI pré-instalada que representa discos lógicos em um sistema de computador baseado no Windows. Dessa forma, a pesquisa dessa classe pai também retorna instâncias de Win32_LogicalDisk, que é o que o Windows usa para descrever discos rígidos. Para obter mais informações, confira Common Information Model. O WMI fornece um esquema inteiro dessas classes pré-instaladas que permitem acessar e controlar objetos gerenciados. Para obter mais informações, confira Classes Win32 e classes do WMI.

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

... localizar um objeto do WMI?

Na API de Scripts para WMI e no PowerShell, o WMI usa uma combinação de namespace, nome de classe e propriedades de chave para identificar exclusivamente uma determinada instância do WMI. Essa combinação é conhecida como o caminho do objeto do WMI. Na VBScript, a propriedade SWbemObject.Path_ descreve o caminho para qualquer objeto retornado pela API de script. No PowerShell, cada objeto do WMI terá uma propriedade __PATH. Para obter mais informações, confira Descrever o local de um objeto do WMI

Além do namespace e do nome da classe, um objeto do WMI também terá uma propriedade de chave, que identifica exclusivamente essa instância em comparação com outras instâncias em seu computador. Por exemplo, a propriedade DeviceID é a propriedade da chave da classe Win32_LogicalDisk. Para obter mais informações, consulte MOF (Managed Object Format).

Por fim, o caminho Relativo é simplesmente uma forma abreviada do caminho e inclui o nome da classe e o valor da chave. Nos exemplos abaixo, o caminho pode ser "\\computerName\root\cimv2:Win32_LogicalDisk.DeviceID="D:"", enquanto o caminho relativo seria ""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  }

... definir informações no WMI?

Na VBScript e na API de Script para WMI, use o método SWbemObject.Put_.

No PowerShell, você pode usar o método Put ou, em seguida, Set-WmiInstance.

Para obter mais informações, consulte Modificar uma propriedade de instância.

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}

...usar credenciais diferentes?

Na VBScript e na API de Script para WMI, use os parâmetros UserName e Password no método SWbemLocator.ConnectServer.

No PowerShell, use o parâmetro -Credential.

Observe que você só pode usar credenciais alternativas em um sistema remoto. Para obter mais informações, confira Proteger clientes de script.

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

... acessar um computador remoto?

Ma VBScript e na API de Script para WMI, declare explicitamente o nome do computador no moniker ou na chamada para SWbemLocator.ConnectServer. Para obter mais informações, confira Conectar-se remotamente ao WMI com VBScript.

No PowerShell, use o parâmetro -ComputerName. Para obter mais informações, confira Conectar-se remotamente ao WMI com o PowerShell.

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

... definir os níveis de Autenticação e Representação?

Na VBScript e na API de Script para WMI, use a propriedade SWbemServices.Security_ no objeto de servidor retornado ou defina os valores relevantes no moniker.

No PowerShell, use os parâmetros -Authentication e -Impersonation, respectivamente. Para obter mais informações, confira Proteger clientes de script.

Para obter mais informações, confira Proteger clientes de script.

' 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

... tratar erros no WMI?

Na API de Script para WMI, o provedor pode fornecer um objeto SWbemLastError para dar mais informações sobre um erro.

Na VBScript, em particular, o tratamento de erros também pode ser feito com o objeto Err nativo. Você também pode acessar o objeto SWbemLastError, conforme descrito acima. Para obter mais informações, confira Recuperar um código de erro.

No PowerShell, você pode usar as técnicas padrão de tratamento de erros do PowerShell. Para obter mais informações, consulte Uma introdução ao tratamento de erros no 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