Capítulo 7 - Trabalhando com WMI
WMI e CIM
O Windows PowerShell é fornecido por padrão com cmdlets para trabalhar com outras tecnologias, como o WMI (Instrumentação de Gerenciamento do Windows). Os cmdlets WMI foram preteridos e não estão disponíveis no PowerShell 6+, mas são abordados aqui, pois você pode encontrá-los em scripts mais antigos em execução no Windows PowerShell. Para novos desenvolvimentos, use os cmdlets CIM.
Há vários cmdlets WMI nativos que existem no PowerShell sem a necessidade de instalar nenhum software ou módulo adicional. Get-Command
pode ser usado para determinar quais cmdlets WMI existem no Windows PowerShell. Os resultados a seguir são do meu computador de ambiente de laboratório do Windows 10 que está executando o PowerShell versão 5.1. Seus resultados podem diferir dependendo da versão do PowerShell que você está executando.
Get-Command -Noun WMI*
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Get-WmiObject 3.1.0.0 Microsof...
Cmdlet Invoke-WmiMethod 3.1.0.0 Microsof...
Cmdlet Register-WmiEvent 3.1.0.0 Microsof...
Cmdlet Remove-WmiObject 3.1.0.0 Microsof...
Cmdlet Set-WmiInstance 3.1.0.0 Microsof...
Os cmdlets CIM (Common Information Model) foram introduzidos no PowerShell versão 3.0. Os cmdlets CIM foram projetados para que possam ser usados em máquinas Windows e não Windows.
Os cmdlets CIM estão todos contidos em um módulo. Para obter uma lista dos cmdlets CIM, use Get-Command
com o parâmetro Module , conforme mostrado no exemplo a seguir.
Get-Command -Module CimCmdlets
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Export-BinaryMiLog 1.0.0.0 CimCmdlets
Cmdlet Get-CimAssociatedInstance 1.0.0.0 CimCmdlets
Cmdlet Get-CimClass 1.0.0.0 CimCmdlets
Cmdlet Get-CimInstance 1.0.0.0 CimCmdlets
Cmdlet Get-CimSession 1.0.0.0 CimCmdlets
Cmdlet Import-BinaryMiLog 1.0.0.0 CimCmdlets
Cmdlet Invoke-CimMethod 1.0.0.0 CimCmdlets
Cmdlet New-CimInstance 1.0.0.0 CimCmdlets
Cmdlet New-CimSession 1.0.0.0 CimCmdlets
Cmdlet New-CimSessionOption 1.0.0.0 CimCmdlets
Cmdlet Register-CimIndicationEvent 1.0.0.0 CimCmdlets
Cmdlet Remove-CimInstance 1.0.0.0 CimCmdlets
Cmdlet Remove-CimSession 1.0.0.0 CimCmdlets
Cmdlet Set-CimInstance 1.0.0.0 CimCmdlets
Os cmdlets CIM ainda permitem que você trabalhe com o WMI, portanto, não se confunda quando alguém fizer a instrução "Quando eu consultar o WMI com os cmdlets CIM do PowerShell..."
Como mencionei anteriormente, o WMI é uma tecnologia separada do PowerShell e você está apenas usando os cmdlets CIM para acessar o WMI. Você pode encontrar um VBScript antigo que usa WMI Query Language (WQL) para consultar WMI, como no exemplo a seguir.
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colBIOS = objWMIService.ExecQuery _
("Select * from Win32_BIOS")
For each objBIOS in colBIOS
Wscript.Echo "Manufacturer: " & objBIOS.Manufacturer
Wscript.Echo "Name: " & objBIOS.Name
Wscript.Echo "Serial Number: " & objBIOS.SerialNumber
Wscript.Echo "SMBIOS Version: " & objBIOS.SMBIOSBIOSVersion
Wscript.Echo "Version: " & objBIOS.Version
Next
Você pode pegar a consulta WQL desse VBScript e usá-la com o Get-CimInstance
cmdlet sem modificações.
Get-CimInstance -Query 'Select * from Win32_BIOS'
SMBIOSBIOSVersion : 090006
Manufacturer : American Megatrends Inc.
Name : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber : 3810-1995-1654-4615-2295-2755-89
Version : VRTUAL - 4001628
Não é assim que normalmente consulto o WMI com o PowerShell. Mas ele funciona e permite migrar facilmente VBScripts existentes para o PowerShell. Quando começo a escrever uma linha única para consultar o WMI, utilizo a sintaxe a seguir.
Get-CimInstance -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer : American Megatrends Inc.
Name : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber : 3810-1995-1654-4615-2295-2755-89
Version : VRTUAL - 4001628
Se eu quiser apenas o número de série, posso canalizar a saída e Select-Object
especificar apenas a propriedade SerialNumber .
Get-CimInstance -ClassName Win32_BIOS | Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89
Por padrão, há várias propriedades recuperadas nos bastidores que nunca são usadas.
Pode não importar muito ao consultar o WMI no computador local. Mas uma vez que você começa a consultar computadores remotos, não é apenas tempo de processamento adicional para retornar essas informações, mas também informações adicionais desnecessárias para ter que puxar pela rede. Get-CimInstance
tem um parâmetro Property que limita as informações recuperadas. Isso torna a consulta ao WMI mais eficiente.
Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89
Os resultados anteriores retornaram um objeto. Para retornar uma cadeia de caracteres simples, use o parâmetro ExpandProperty .
Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
Select-Object -ExpandProperty SerialNumber
3810-1995-1654-4615-2295-2755-89
Você também pode usar o estilo pontilhado de sintaxe para retornar uma cadeia de caracteres simples. Isso elimina a necessidade de canalizar para Select-Object
.
(Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber).SerialNumber
3810-1995-1654-4615-2295-2755-89
Consultar computadores remotos com os cmdlets CIM
Ainda estou executando o PowerShell como um administrador local que é um usuário de domínio. Quando tento consultar informações de um computador remoto usando o cmdlet, recebo Get-CimInstance
uma mensagem de erro de acesso negado.
Get-CimInstance -ComputerName dc01 -ClassName Win32_BIOS
Get-CimInstance : Access is denied.
At line:1 char:1
+ Get-CimInstance -ComputerName dc01 -ClassName Win32_BIOS
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (root\cimv2:Win32_BIOS:String) [Get-CimI
nstance], CimException
+ FullyQualifiedErrorId : HRESULT 0x80070005,Microsoft.Management.Infrastructure.Cim
Cmdlets.GetCimInstanceCommand
+ PSComputerName : dc01
Muitas pessoas têm preocupações de segurança quando se trata do PowerShell, mas a verdade é que você tem exatamente as mesmas permissões no PowerShell que na GUI. Nem mais, nem menos. O problema no exemplo anterior é que o usuário que executa o PowerShell não tem direitos para consultar informações WMI do servidor DC01. Eu poderia reiniciar o PowerShell como administrador de domínio, pois Get-CimInstance
não tem um parâmetro Credential . Mas, acredite, isso não é uma boa ideia, porque então qualquer coisa que eu execute a partir do PowerShell estaria sendo executada como um administrador de domínio. Isso pode ser perigoso do ponto de vista da segurança, dependendo da situação.
Usando o princípio de menor privilégio, elevo para minha conta de administrador de domínio por comando usando o parâmetro Credential , se um comando tiver um. Get-CimInstance
não tem um parâmetro Credential , portanto, a solução neste cenário é criar um CimSession primeiro. Em seguida, uso o CimSession em vez de um nome de computador para consultar o WMI no computador remoto.
$CimSession = New-CimSession -ComputerName dc01 -Credential (Get-Credential)
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential
A sessão CIM foi armazenada em uma variável chamada $CimSession
. Observe que também especifiquei o Get-Credential
cmdlet entre parênteses para que ele seja executado primeiro, solicitando credenciais alternativas, antes de criar a nova sessão. Mostrarei outra maneira mais eficiente de especificar credenciais alternativas mais adiante neste capítulo, mas é importante entender esse conceito básico antes de torná-lo mais complicado.
A sessão CIM criada no exemplo anterior agora pode ser usada com o Get-CimInstance
cmdlet para consultar as informações do BIOS do WMI no computador remoto.
Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer : American Megatrends Inc.
Name : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber : 0986-6980-3916-0512-6608-8243-13
Version : VRTUAL - 4001628
PSComputerName : dc01
Há vários benefícios adicionais em usar sessões CIM em vez de apenas especificar um nome de computador. Ao executar várias consultas no mesmo computador, usar uma sessão CIM é mais eficiente do que usar o nome do computador para cada consulta. Criar uma sessão CIM só configura a conexão uma vez. Em seguida, várias consultas usam essa mesma sessão para recuperar informações. O uso do nome do computador requer que os cmdlets configurem e destruam a conexão com cada consulta individual.
O Get-CimInstance
cmdlet usa o protocolo WSMan por padrão, o que significa que o computador remoto precisa do PowerShell versão 3.0 ou superior para se conectar. Na verdade, não é a versão do PowerShell que importa, é a versão da pilha. A versão da pilha pode ser determinada usando o Test-WSMan
cmdlet.
Precisa ser a versão 3.0. Essa é a versão que você encontrará com o PowerShell versão 3.0 e superior.
Test-WSMan -ComputerName dc01
wsmid : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd
ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor : Microsoft Corporation
ProductVersion : OS: 0.0.0 SP: 0.0 Stack: 3.0
Os cmdlets WMI mais antigos usam o protocolo DCOM, que é compatível com versões mais antigas do Windows. Mas o DCOM normalmente é bloqueado pelo firewall em versões mais recentes do Windows. O New-CimSessionOption
cmdlet permite criar uma conexão de protocolo DCOM para uso com New-CimSession
o . Isso permite que o cmdlet seja usado para se comunicar com versões do Windows tão antigas quanto o Get-CimInstance
Windows Server 2000. Isso também significa que o PowerShell não é necessário no computador remoto ao usar o Get-CimInstance
cmdlet com um CimSession configurado para usar o protocolo DCOM.
Crie a opção de protocolo DCOM usando o New-CimSessionOption
cmdlet e armazene-a em uma variável.
$DCOM = New-CimSessionOption -Protocol Dcom
Para maior eficiência, você pode armazenar suas credenciais de administrador de domínio ou elevadas em uma variável para não precisar inseri-las constantemente para cada comando.
$Cred = Get-Credential
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential
Tenho um servidor chamado SQL03 que executa o Windows Server 2008 (não R2). É o mais novo sistema operacional Windows Server que não tem o PowerShell instalado por padrão.
Crie um CimSession para SQL03 usando o protocolo DCOM.
$CimSession = New-CimSession -ComputerName sql03 -SessionOption $DCOM -Credential $Cred
Observe que no comando anterior, desta vez especifiquei a variável nomeada $Cred
como o valor para o parâmetro Credential em vez de ter que inseri-los manualmente novamente.
A saída da consulta é a mesma, independentemente do protocolo subjacente que está sendo usado.
Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer : American Megatrends Inc.
Name : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber : 7237-7483-8873-8926-7271-5004-86
Version : VRTUAL - 4001628
PSComputerName : sql03
O Get-CimSession
cmdlet é usado para ver quais CimSessions estão conectados atualmente e quais protocolos eles estão usando.
Get-CimSession
Id : 1
Name : CimSession1
InstanceId : 80742787-e38e-41b1-a7d7-fa1369cf1402
ComputerName : dc01
Protocol : WSMAN
Id : 2
Name : CimSession2
InstanceId : 8fcabd81-43cf-4682-bd53-ccce1e24aecb
ComputerName : sql03
Protocol : DCOM
Recupere e armazene ambos os CimSessions criados anteriormente em uma variável chamada $CimSession
.
$CimSession = Get-CimSession
Consulte ambos os computadores com um comando, um usando o protocolo WSMan e o outro com DCOM.
Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer : American Megatrends Inc.
Name : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber : 0986-6980-3916-0512-6608-8243-13
Version : VRTUAL - 4001628
PSComputerName : dc01
SMBIOSBIOSVersion : 090006
Manufacturer : American Megatrends Inc.
Name : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber : 7237-7483-8873-8926-7271-5004-86
Version : VRTUAL - 4001628
PSComputerName : sql03
Escrevi vários artigos de blog sobre os cmdlets WMI e CIM. Uma das mais úteis é sobre uma função que criei para determinar automaticamente se o WSMan ou DCOM deve ser usado e configurar a sessão CIM automaticamente sem ter que descobrir qual manualmente. Esse artigo do blog é intitulado Função do PowerShell para criar CimSessions para computadores remotos com fallback para Dcom.
Quando terminar as sessões CIM, você deve removê-las com o Remove-CimSession
cmdlet. Para remover todas as sessões CIM, basta canalizar Get-CimSession
para Remove-CimSession
.
Get-CimSession | Remove-CimSession
Resumo
Neste capítulo, você aprendeu sobre como usar o PowerShell para trabalhar com WMI em computadores locais e remotos. Você também aprendeu como usar os cmdlets CIM para trabalhar com computadores remotos com o protocolo WSMan ou DCOM.
Rever
- Qual é a diferença nos cmdlets WMI e CIM?
- Por padrão, qual protocolo o
Get-CimInstance
cmdlet usa? - Quais são alguns dos benefícios de usar uma sessão CIM em vez de especificar um nome de computador com
Get-CimInstance
? - Como você especifica um protocolo alternativo diferente do padrão para uso com
Get-CimInstance
? - Como fechar ou remover sessões CIM?