Bab 7 - Bekerja dengan WMI

WMI dan CIM

Windows PowerShell dikirim secara default dengan cmdlet untuk bekerja dengan teknologi lain seperti Windows Management Instrumentation (WMI). Cmdlet WMI tidak digunakan lagi dan tidak tersedia di PowerShell 6+, tetapi dibahas di sini karena Anda mungkin menemukannya dalam skrip lama yang berjalan di Windows PowerShell. Untuk pengembangan baru, gunakan cmdlet CIM sebagai gantinya.

Ada beberapa cmdlet WMI asli yang ada di PowerShell tanpa harus menginstal perangkat lunak atau modul tambahan apa pun. Get-Command dapat digunakan untuk menentukan cmdlet WMI apa yang ada di Windows PowerShell. Hasil berikut berasal dari komputer lingkungan lab Windows 10 saya yang menjalankan PowerShell versi 5.1. Hasil Anda mungkin berbeda tergantung pada versi PowerShell apa yang Anda jalankan.

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...

Cmdlet Common Information Model (CIM) diperkenalkan di PowerShell versi 3.0. Cmdlet CIM dirancang agar dapat digunakan pada komputer Windows dan non-Windows.

Cmdlet CIM semuanya terkandung dalam modul. Untuk mendapatkan daftar cmdlet CIM, gunakan Get-Command dengan parameter Modul seperti yang ditunjukkan dalam contoh berikut.

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

Cmdlet CIM masih memungkinkan Anda untuk bekerja dengan WMI jadi jangan bingung ketika seseorang membuat pernyataan "Ketika saya mengkueri WMI dengan cmdlet POWERShell CIM..."

Seperti yang saya sebutkan sebelumnya, WMI adalah teknologi terpisah dari PowerShell dan Anda hanya menggunakan cmdlet CIM untuk mengakses WMI. Anda mungkin menemukan VBScript lama yang menggunakan WMI Query Language (WQL) untuk mengkueri WMI seperti dalam contoh berikut.

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

Anda dapat mengambil kueri WQL dari VBScript tersebut Get-CimInstance dan menggunakannya dengan cmdlet tanpa modifikasi apa pun.

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

Bukan itu cara saya biasanya mengkueri WMI dengan PowerShell. Tetapi ini berfungsi dan memungkinkan Anda untuk dengan mudah memigrasikan VBScript yang ada ke PowerShell. Saat saya mulai menulis satu baris untuk mengkueri WMI, saya menggunakan sintaks berikut.

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

Jika saya hanya menginginkan nomor seri, saya dapat menyalurkan output ke Select-Object dan menentukan hanya properti SerialNumber .

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

Secara default, ada beberapa properti yang diambil di belakang layar yang tidak pernah digunakan. Mungkin tidak terlalu penting saat mengkueri WMI di komputer lokal. Tetapi setelah Anda mulai mengkueri komputer jarak jauh, tidak hanya waktu pemrosesan tambahan untuk mengembalikan informasi tersebut, tetapi juga informasi tambahan yang tidak perlu harus ditarik ke seluruh jaringan. Get-CimInstance memiliki parameter Properti yang membatasi informasi yang diambil. Ini membuat kueri ke WMI lebih efisien.

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

Hasil sebelumnya mengembalikan objek. Untuk mengembalikan string sederhana, gunakan parameter ExpandProperty .

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

Anda juga dapat menggunakan gaya sintaksis putus-putus untuk mengembalikan string sederhana. Ini menghilangkan kebutuhan untuk menyalurkan ke Select-Object.

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

Mengkueri Komputer Jarak Jauh dengan cmdlet CIM

Saya masih menjalankan PowerShell sebagai admin lokal yang merupakan pengguna domain. Ketika saya mencoba mengkueri informasi dari komputer jarak jauh menggunakan Get-CimInstance cmdlet, saya menerima pesan kesalahan akses ditolak.

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

Banyak orang memiliki masalah keamanan ketika datang ke PowerShell, tetapi sebenarnya Anda memiliki izin yang sama persis di PowerShell seperti yang Anda lakukan di GUI. Tidak lebih dan tidak kurang. Masalah dalam contoh sebelumnya adalah bahwa pengguna yang menjalankan PowerShell tidak memiliki hak untuk mengkueri informasi WMI dari server DC01. Saya dapat merilis kembali PowerShell sebagai administrator domain karena Get-CimInstance tidak memiliki parameter Kredensial . Tapi, percayalah, itu bukan ide yang baik karena maka apa pun yang saya jalankan dari PowerShell akan berjalan sebagai admin domain. Itu bisa berbahaya dari sudut siaga keamanan tergantung pada situasinya.

Dengan menggunakan prinsip hak istimewa paling sedikit, saya meningkatkan ke akun admin domain saya berdasarkan per perintah menggunakan parameter Kredensial , jika perintah memilikinya. Get-CimInstance tidak memiliki parameter Kredensial sehingga solusi dalam skenario ini adalah membuat CimSession terlebih dahulu. Kemudian saya menggunakan CimSession alih-alih nama komputer untuk mengkueri WMI di komputer jarak jauh.

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

Sesi CIM disimpan dalam variabel bernama $CimSession. Perhatikan bahwa saya juga menentukan Get-Credential cmdlet dalam tanda kurung sehingga dijalankan terlebih dahulu, meminta kredensial alternatif kepada saya, sebelum membuat sesi baru. Saya akan menunjukkan cara lain yang lebih efisien untuk menentukan kredensial alternatif nanti dalam bab ini, tetapi penting untuk memahami konsep dasar ini sebelum membuatnya lebih rumit.

Sesi CIM yang dibuat dalam contoh sebelumnya sekarang dapat digunakan dengan Get-CimInstance cmdlet untuk mengkueri informasi BIOS dari WMI di komputer jarak jauh.

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

Ada beberapa manfaat tambahan untuk menggunakan sesi CIM alih-alih hanya menentukan nama komputer. Saat menjalankan beberapa kueri ke komputer yang sama, menggunakan sesi CIM lebih efisien daripada menggunakan nama komputer untuk setiap kueri. Membuat sesi CIM hanya menyiapkan koneksi sekali. Kemudian, beberapa kueri menggunakan sesi yang sama untuk mengambil informasi. Menggunakan nama komputer mengharuskan cmdlet untuk menyiapkan dan merobek koneksi dengan setiap kueri individual.

Get-CimInstance Cmdlet menggunakan protokol WSMan secara default, yang berarti komputer jarak jauh membutuhkan PowerShell versi 3.0 atau yang lebih tinggi untuk terhubung. Sebenarnya bukan versi PowerShell yang penting, ini adalah versi tumpukan. Versi tumpukan dapat ditentukan menggunakan Test-WSMan cmdlet. Ini harus versi 3.0. Itulah versi yang akan Anda temukan dengan PowerShell versi 3.0 dan yang lebih tinggi.

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

Cmdlet WMI yang lebih lama menggunakan protokol DCOM, yang kompatibel dengan versi Windows yang lebih lama. Tetapi DCOM biasanya diblokir oleh firewall pada versi Windows yang lebih baru. New-CimSessionOption Cmdlet memungkinkan Anda membuat koneksi protokol DCOM untuk digunakan dengan New-CimSession. Ini memungkinkan Get-CimInstance cmdlet digunakan untuk berkomunikasi dengan versi Windows setingkat Windows Server 2000. Ini juga berarti bahwa PowerShell tidak diperlukan di komputer jarak jauh saat menggunakan Get-CimInstance cmdlet dengan CimSession yang dikonfigurasi untuk menggunakan protokol DCOM.

Buat opsi protokol DCOM menggunakan New-CimSessionOption cmdlet dan simpan dalam variabel.

$DCOM = New-CimSessionOption -Protocol Dcom

Untuk efisiensi, Anda dapat menyimpan administrator domain atau kredensial yang ditinggikan dalam variabel sehingga Anda tidak perlu terus-menerus memasukkannya untuk setiap perintah.

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

Saya memiliki server bernama SQL03 yang menjalankan Windows Server 2008 (non-R2). Ini adalah sistem operasi Windows Server terbaru yang tidak menginstal PowerShell secara default.

Buat CimSession ke SQL03 menggunakan protokol DCOM.

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

Perhatikan dalam perintah sebelumnya, kali ini saya menentukan variabel bernama $Cred sebagai nilai untuk parameter Kredensial alih-alih harus memasukkannya secara manual lagi.

Output kueri sama terlepas dari protokol yang mendasar yang digunakan.

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

Get-CimSession Cmdlet digunakan untuk melihat apa yang saat ini terhubung dengan CimSessions dan protokol apa yang mereka gunakan.

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

Ambil dan simpan kedua CimSessions yang dibuat sebelumnya dalam variabel bernama $CimSession.

$CimSession = Get-CimSession

Kueri kedua komputer dengan satu perintah, satu menggunakan protokol WSMan dan yang lainnya dengan 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

Saya telah menulis banyak artikel blog tentang cmdlet WMI dan CIM. Salah satu yang paling berguna adalah tentang fungsi yang saya buat untuk secara otomatis menentukan apakah WSMan atau DCOM harus digunakan dan mengatur sesi CIM secara otomatis tanpa harus mencari tahu mana yang secara manual. Artikel blog tersebut berjudul Fungsi PowerShell untuk Membuat CimSessions ke Komputer Jarak Jauh dengan Fallback ke Dcom.

Setelah selesai dengan sesi CIM, Anda harus menghapusnya dengan Remove-CimSession cmdlet. Untuk menghapus semua sesi CIM, cukup pipa Get-CimSession ke Remove-CimSession.

Get-CimSession | Remove-CimSession

Ringkasan

Dalam bab ini, Anda telah mempelajari tentang menggunakan PowerShell untuk bekerja dengan WMI di komputer lokal dan jarak jauh. Anda juga telah mempelajari cara menggunakan cmdlet CIM untuk bekerja dengan komputer jarak jauh dengan protokol WSMan atau DCOM.

Tinjauan

  1. Apa perbedaan dalam cmdlet WMI dan CIM?
  2. Secara default, protokol Get-CimInstance apa yang digunakan cmdlet?
  3. Apa saja manfaat menggunakan sesi CIM alih-alih menentukan nama komputer dengan Get-CimInstance?
  4. Bagaimana Anda menentukan protokol alternatif selain protokol default untuk digunakan dengan Get-CimInstance?
  5. Bagaimana Anda menutup atau menghapus sesi CIM?