Condividi tramite


Capitolo 7 - Uso di WMI

WMI e CIM

Windows PowerShell viene fornito per impostazione predefinita con i cmdlet per l'uso di altre tecnologie, ad esempio Strumentazione gestione Windows (WMI). I cmdlet WMI sono deprecati e non sono disponibili in PowerShell 6+, ma sono illustrati qui come potrebbero verificarsi negli script meno recenti in esecuzione in Windows PowerShell. Per il nuovo sviluppo, usare invece i cmdlet CIM.

In PowerShell esistono diversi cmdlet WMI nativi senza dover installare altri software o moduli. Get-Command può essere usato per determinare quali cmdlet WMI esistono in Windows PowerShell. I risultati seguenti provengono da un sistema Windows 11 che esegue PowerShell versione 5.1. I risultati potrebbero variare a seconda della versione di PowerShell in esecuzione.

Get-Command -Noun WMI*
CommandType     Name                                               Version
-----------     ----                                               -------
Cmdlet          Get-WmiObject                                      3.1.0.0
Cmdlet          Invoke-WmiMethod                                   3.1.0.0
Cmdlet          Register-WmiEvent                                  3.1.0.0
Cmdlet          Remove-WmiObject                                   3.1.0.0
Cmdlet          Set-WmiInstance                                    3.1.0.0

I cmdlet CIM (Common Information Model) sono stati introdotti in PowerShell 3.0 e sono raggruppati all'interno di un modulo dedicato. Per elencare tutti i cmdlet CIM disponibili, usare il cmdlet Get-Command con il parametro Module, come illustrato nell'esempio seguente.

Get-Command -Module CimCmdlets
CommandType     Name                                               Version
-----------     ----                                               -------
Cmdlet          Export-BinaryMiLog                                 1.0.0.0
Cmdlet          Get-CimAssociatedInstance                          1.0.0.0
Cmdlet          Get-CimClass                                       1.0.0.0
Cmdlet          Get-CimInstance                                    1.0.0.0
Cmdlet          Get-CimSession                                     1.0.0.0
Cmdlet          Import-BinaryMiLog                                 1.0.0.0
Cmdlet          Invoke-CimMethod                                   1.0.0.0
Cmdlet          New-CimInstance                                    1.0.0.0
Cmdlet          New-CimSession                                     1.0.0.0
Cmdlet          New-CimSessionOption                               1.0.0.0
Cmdlet          Register-CimIndicationEvent                        1.0.0.0
Cmdlet          Remove-CimInstance                                 1.0.0.0
Cmdlet          Remove-CimSession                                  1.0.0.0
Cmdlet          Set-CimInstance                                    1.0.0.0

I cmdlet CIM consentono comunque di lavorare con WMI, quindi non essere confusi quando qualcuno afferma: "Quando si esegue una query WMI con i cmdlet CIM di PowerShell".

Come accennato in precedenza, WMI è una tecnologia separata da PowerShell e si usano solo i cmdlet CIM per accedere a WMI. È possibile trovare un codice VBScript precedente che usa WQL (WMI Query Language) per eseguire query su WMI, ad esempio nell'esempio seguente.

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

È possibile eseguire la query WQL da VBScript e usarla con il cmdlet Get-CimInstance senza apportare modifiche.

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

L'esempio precedente non è il modo in cui in genere si esegue una query WMI con PowerShell. Ma funziona e consente di eseguire facilmente la migrazione di script Visual Basic esistenti a PowerShell. Quando si scrive una riga di comando per eseguire query su WMI, si usa la sintassi seguente.

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 si desidera solo il numero di serie, inviare tramite pipe l'output a Select-Object e specificare solo la proprietà SerialNumber.

Get-CimInstance -ClassName Win32_BIOS |
    Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89

Per impostazione predefinita, quando si esegue una query su WMI, vengono recuperate diverse proprietà che non vengono mai usate in background. Non ha molta importanza eseguire una query WMI sul computer locale. Tuttavia, quando si inizia a eseguire query sui computer remoti, non è solo un tempo di elaborazione aggiuntivo per restituire tali informazioni, ma anche informazioni più inutili da inviare attraverso la rete. Get-CimInstance ha un parametro Property che limita le informazioni recuperate, rendendo la query WMI più efficiente.

Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
    Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89

I risultati precedenti hanno restituito un oggetto . Per restituire una stringa, usare il parametro ExpandProperty.

Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
    Select-Object -ExpandProperty SerialNumber
3810-1995-1654-4615-2295-2755-89

È anche possibile usare lo stile della sintassi punteggiata per restituire una stringa, eliminando la necessità di inviare pipe a Select-Object.

(Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber).SerialNumber
3810-1995-1654-4615-2295-2755-89

Eseguire query su computer remoti con i cmdlet CIM

È comunque consigliabile eseguire PowerShell come amministratore locale e utente di dominio. Quando si tenta di eseguire query sulle informazioni da un computer remoto usando il cmdlet Get-CimInstance, viene visualizzato un messaggio di errore di accesso negato.

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:Stri
   ng) [Get-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80070005,Microsoft.Management.Infra
   structure.CimCmdlets.GetCimInstanceCommand
    + PSComputerName        : dc01

Molte persone hanno problemi di sicurezza relativi a PowerShell, ma si hanno le stesse autorizzazioni in PowerShell come nell'interfaccia utente grafica. Non più e non meno. Il problema nell'esempio precedente è che l'utente che esegue PowerShell non dispone dei diritti per eseguire query sulle informazioni WMI dal server DC01. È possibile riavviare PowerShell come amministratore di dominio perché Get-CimInstance non ha un parametro Credential. Ma questa non è una buona idea perché qualsiasi operazione eseguita da PowerShell verrebbe eseguita come amministratore di dominio. A seconda della situazione, tale scenario potrebbe essere pericoloso dal punto di vista della sicurezza.

Utilizzando il principio del minimo privilegio, elevare i privilegi al livello di amministratore di dominio per ogni comando usando il parametro Credential, se disponibile per quel comando. Get-CimInstance non dispone di un parametro di credenziali , quindi la soluzione in questo scenario consiste nel creare un CimSession prima. Usare quindi il CimSession anziché un nome computer per eseguire query su WMI nel computer remoto.

$CimSession = New-CimSession -ComputerName dc01 -Credential (Get-Credential)
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential

La sessione CIM è stata archiviata in una variabile denominata $CimSession. Si noti anche che si specifica il cmdlet Get-Credential tra parentesi in modo che venga eseguito per primo, richiedendo credenziali alternative, prima di creare la nuova sessione. Vi mostrerò un altro modo più efficiente per specificare credenziali alternative più avanti in questo capitolo, ma è importante comprendere questo concetto di base prima di renderlo più complicato.

È ora possibile usare la sessione CIM creata nell'esempio precedente con il cmdlet Get-CimInstance per eseguire query sulle informazioni DEL BIOS da WMI nel computer 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

Esistono diversi altri vantaggi per l'uso di sessioni CIM invece di specificare solo un nome computer. Quando si eseguono più query nello stesso computer, l'uso di una sessione CIM è più efficiente rispetto all'uso del nome computer per ogni query. La creazione di una sessione CIM configura la connessione una sola volta. Poi, più query utilizzano la stessa sessione per recuperare informazioni. L'uso del nome del computer richiede che i cmdlet configurino e dismettano la connessione con ogni query.

Il cmdlet Get-CimInstance usa il protocollo WSMan per impostazione predefinita, il che significa che il computer remoto richiede PowerShell versione 3.0 o successiva per connettersi. In realtà non è la versione di PowerShell importante, è la versione dello stack. È possibile determinare la versione dello stack usando il cmdlet Test-WSMan. Deve essere la versione 3.0, disponibile con PowerShell versione 3.0 e successive.

Test-WSMan -ComputerName dc01
wsmid           : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentit
                  y.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

I cmdlet WMI precedenti usano il protocollo DCOM, compatibile con le versioni precedenti di Windows. Tuttavia, il firewall blocca in genere DCOM nelle versioni più recenti di Windows. Il cmdlet New-CimSessionOption consente di creare una connessione al protocollo DCOM da usare con New-CimSession. Questa opzione consente al cmdlet Get-CimInstance di comunicare con le versioni di Windows precedenti a Windows Server 2000. Questa capacità significa anche che PowerShell non è necessario nel computer remoto quando si usa il cmdlet Get-CimInstance con una CimSession configurata per l'uso del protocollo DCOM.

Creare l'opzione del protocollo DCOM usando il cmdlet New-CimSessionOption e archiviarla in una variabile.

$DCOM = New-CimSessionOption -Protocol Dcom

Per un'efficienza, è possibile archiviare l'amministratore di dominio o le credenziali con privilegi elevati in una variabile, in modo che non sia necessario immetterle costantemente per ogni comando.

$Cred = Get-Credential
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential

Si dispone di un server denominato SQL03 che esegue Windows Server 2008 (non R2). Si tratta del sistema operativo Windows Server più recente che non ha PowerShell installato per impostazione predefinita.

Creare una CimSession per SQL03 utilizzando il protocollo DCOM.

$CimSession = New-CimSession -ComputerName sql03 -SessionOption $DCOM -Credential $Cred

Si noti nel comando precedente che si specifica la variabile denominata $Cred come valore per il parametro Credential anziché immettere di nuovo manualmente le credenziali.

L'output della query è lo stesso indipendentemente dal protocollo sottostante.

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

Il cmdlet Get-CimSession viene usato per vedere quali cimSession sono attualmente connessi e quali protocolli usano.

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

Recuperare e archiviare i CimSession creati in precedenza in una variabile denominata $CimSession.

$CimSession = Get-CimSession

Eseguire query su entrambi i computer con un comando, uno usando il protocollo WSMan e l'altro con 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

Uno degli articoli del blog sui cmdlet WMI e CIM include una funzione di PowerShell che rileva automaticamente se usare WSMan o DCOM e quindi configura automaticamente la sessione CIM appropriata. Per ulteriori informazioni, vedere funzione PowerShell per creare sessioni CimSession su computer remoti con fallback a DCOM.

Al termine delle sessioni CIM, rimuoverle con il cmdlet Remove-CimSession. Per rimuovere tutte le sessioni CIM, passare tramite pipe Get-CimSession a Remove-CimSession.

Get-CimSession | Remove-CimSession

Sommario

In questo capitolo si è appreso come usare PowerShell per lavorare con WMI nei computer locali e remoti. Si è anche appreso come usare i cmdlet CIM per lavorare con i computer remoti usando i protocolli WSMan e DCOM.

Recensione

  1. Qual è la differenza tra i cmdlet WMI e CIM?
  2. Per impostazione predefinita, quale protocollo usa il cmdlet Get-CimInstance?
  3. Quali sono alcuni vantaggi dell'uso di una sessione CIM invece di specificare un nome computer con Get-CimInstance?
  4. Come si specifica un protocollo alternativo diverso da quello predefinito da usare con Get-CimInstance?
  5. Come si chiude o si rimuovono le sessioni CIM?

Riferimenti