WMI ile çalışma


WMI ve CIM

Windows PowerShell, Windows Yönetim Araçları (WMI) gibi diğer teknolojilerle çalışmak için varsayılan olarak cmdlet'lerle birlikte gelir. WMI cmdlet'leri kullanımdan kaldırılmıştır ve PowerShell 6+ sürümünde mevcut değildir, ancak Windows PowerShell'de çalışan eski komut dosyalarında karşılaşabileceğiniz için burada ele alınmıştır. Yeni geliştirmeler için bunun yerine CIM cmdlet'lerini kullanın.

PowerShell'de herhangi bir ek yazılım veya modül yüklemeye gerek kalmadan kullanılabilen birkaç yerel WMI cmdlet'i vardır. Get-Command, Windows PowerShell'de hangi WMI cmdlet'lerinin bulunduğunu belirlemek için kullanılabilir. Aşağıdaki sonuçlar PowerShell sürüm 5.1 çalıştıran Windows 10 laboratuvar ortamı bilgisayarımdan alınmıştır. Sonuçlarınız, çalıştırdığınız PowerShell sürümüne bağlı olarak farklılık gösterebilir.

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

Ortak Bilgi Modeli (CIM) cmdlet'leri PowerShell sürüm 3.0'da kullanıma sunuldu. CIM cmdlet'leri hem Windows hem de Windows olmayan makinelerde kullanılabilecek şekilde tasarlanmıştır.

CIM cmdlet'lerinin tümü bir modül içinde bulunur. CIM cmdlet'lerinin bir listesini elde etmek için aşağıdaki örnekte gösterildiği gibi Module parametresiyle Get-Command'ı kullanın.

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

CIM cmdlet'leri hala WMI ile çalışmanıza izin veriyor; bu nedenle birisi "WMI'yı PowerShell CIM cmdlet'leriyle sorguladığımda..." ifadesini kullandığında kafanız karışmasın.

Daha önce de belirttiğim gibi WMI, PowerShell'den ayrı bir teknolojidir ve WMI'ya erişmek için yalnızca CIM cmdlet'lerini kullanıyorsunuz. Aşağıdaki örnekte olduğu gibi WMI sorgulamak için WMI Sorgu Dili (WQL) kullanan eski bir VBScript bulabilirsiniz.

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

WQL sorgusunu bu VBScript'ten alıp Get-CimInstance cmdlet'iyle hiçbir değişiklik yapmadan kullanabilirsiniz.

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

PowerShell ile WMI'yı genellikle bu şekilde sorgulamam. Ancak işe yarıyor ve mevcut VBScript'leri PowerShell'e kolayca taşımanıza olanak tanıyor. WMI'yi sorgulamak için tek satırlık bir yazı yazmaya başladığımda aşağıdaki sözdizimini kullanıyorum.

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

Yalnızca seri numarasını istersem, çıktıyı Select-Object'e yönlendirebilir ve yalnızca SerialNumber özelliğini belirtebilirim.

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

Varsayılan olarak, hiçbir zaman kullanılmayan, perde arkasında alınan çeşitli özellikler vardır. Yerel bilgisayarda WMI sorgularken pek bir önemi olmayabilir. Ancak uzaktaki bilgisayarları sorgulamaya başladığınızda, yalnızca bu bilgiyi döndürmek için ek işlem süresi değil, aynı zamanda ağ üzerinden çekilmesi gereken ek gereksiz bilgiler de söz konusudur. Get-CimInstance, alınan bilgileri sınırlayan bir Özellik parametresine sahiptir. Bu, WMI sorgusunu daha verimli hale getirir.

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

Önceki sonuçlar bir nesne döndürdü. Basit bir dize döndürmek için ExpandProperty parametresini kullanın.

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

Basit bir dize döndürmek için noktalı söz dizimi stilini de kullanabilirsiniz. Bu, Select-Object'e yönlendirme ihtiyacını ortadan kaldırır.

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

CIM cmdlet'leriyle Uzak Bilgisayarları Sorgulama

PowerShell'i hâlâ etki alanı kullanıcısı olan yerel yönetici olarak çalıştırıyorum. Get-CimInstance cmdlet'ini kullanarak uzak bir bilgisayardan bilgi sorgulamaya çalıştığımda erişim reddedildi hata mesajı alıyorum.

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

Konu PowerShell olduğunda birçok kişinin güvenlik endişeleri vardır, ancak gerçek şu ki PowerShell'de de GUI'de sahip olduğunuz izinlerin tamamen aynısına sahipsiniz. Ne daha fazlası ne de daha azı. Önceki örnekteki sorun, PowerShell çalıştıran kullanıcının DC01 sunucusundan WMI bilgilerini sorgulama hakkına sahip olmamasıdır. Get-CimInstance'ın Kimlik Bilgisi parametresi olmadığından PowerShell'i etki alanı yöneticisi olarak yeniden başlatabilirim. Ancak güvenin bana, bu iyi bir fikir değil çünkü o zaman PowerShell'den çalıştırdığım her şey etki alanı yöneticisi olarak çalışıyor olacaktır. Bu, duruma bağlı olarak güvenlik açısından tehlikeli olabilir.

En az ayrıcalık ilkesini kullanarak, eğer bir komutta varsa Kimlik Bilgisi parametresini kullanarak her komut için etki alanı yönetici hesabıma yükseliyorum. Get-CimInstance'ın Kimlik Bilgisi parametresi yoktur, dolayısıyla bu senaryodaki çözüm öncelikle bir CimSession oluşturmaktır. Daha sonra uzak bilgisayardaki WMI'yi sorgulamak için bilgisayar adı yerine CimSession'u kullanıyorum.

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

CIM oturumu $CimSession adlı bir değişkende saklandı. Ayrıca, yeni oturumu oluşturmadan önce benden alternatif kimlik bilgilerini isteyecek şekilde Get-Credential cmdlet'ini parantez içinde belirttiğime dikkat edin. Bu bölümün ilerleyen kısımlarında alternatif kimlik bilgilerini belirlemenin daha etkili başka bir yolunu size göstereceğim, ancak konuyu daha karmaşık hale getirmeden önce bu temel kavramı anlamak önemlidir.

Önceki örnekte oluşturulan CIM oturumu artık uzak bilgisayardaki WMI'dan BIOS bilgilerini sorgulamak için Get-CimInstance cmdlet'iyle birlikte kullanılabilir.

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

Yalnızca bir bilgisayar adı belirtmek yerine CIM oturumlarını kullanmanın birçok ek faydası vardır. Aynı bilgisayarda birden fazla sorgu çalıştırırken, CIM oturumu kullanmak, her sorgu için bilgisayar adını kullanmaktan daha verimlidir. CIM oturumu oluşturmak bağlantıyı yalnızca bir kez kurar. Daha sonra birden çok sorgu, bilgi almak için aynı oturumu kullanır. Bilgisayar adını kullanmak, cmdlet'lerin her bir sorguyla bağlantıyı kurmasını ve kesmesini gerektirir.

Get-CimInstance cmdlet'i varsayılan olarak WSMan protokolünü kullanır; bu, uzak bilgisayarın bağlanmak için PowerShell sürüm 3.0 veya daha yeni bir sürüme ihtiyacı olduğu anlamına gelir. Aslında önemli olan PowerShell sürümü değil, yığın sürümüdür. Yığın sürümü Test-WSMan cmdlet'i kullanılarak belirlenebilir. Versiyon 3.0 olması gerekiyor. PowerShell sürüm 3.0 ve sonraki sürümlerde bulacağınız sürüm budur.

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

Eski WMI cmdlet'leri, Windows'un eski sürümleriyle uyumlu olan DCOM protokolünü kullanır. Ancak DCOM, Windows'un daha yeni sürümlerinde genellikle güvenlik duvarı tarafından engellenir. New-CimSessionOption cmdlet'i, New-CimSession ile kullanılmak üzere bir DCOM protokolü bağlantısı oluşturmanıza olanak tanır. Bu, Get-CimInstance cmdlet'inin Windows Server 2000 kadar eski Windows sürümleriyle iletişim kurmak için kullanılmasına olanak tanır. Bu aynı zamanda Get- kullanılırken uzaktaki bilgisayarda PowerShell'in gerekli olmadığı anlamına gelir. DCOM protokolünü kullanacak şekilde yapılandırılmış bir CimSession içeren CimInstance cmdlet'i.

New-CimSessionOption cmdlet'ini kullanarak DCOM protokolü seçeneğini oluşturun ve bunu bir değişkende saklayın.

$DCOM = New-CimSessionOption -Protocol Dcom

Verimlilik sağlamak için, etki alanı yöneticinizi veya yükseltilmiş kimlik bilgilerini bir değişkende saklayabilirsiniz, böylece her komut için bunları sürekli olarak girmenize gerek kalmaz.

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

Windows Server 2008 (R2 olmayan) çalıştıran SQL03 adında bir sunucum var. Varsayılan olarak PowerShell'in yüklü olmadığı en yeni Windows Server işletim sistemidir.

DCOM protokolünü kullanarak SQL03'e bir CimSession oluşturun.

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

Önceki komutta dikkat edin, bu sefer manuel olarak tekrar girmek zorunda kalmak yerine Kimlik Bilgisi parametresinin değeri olarak $Cred adlı değişkeni belirttim.

Sorgunun çıktısı, kullanılan temel protokolden bağımsız olarak aynıdır.

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'i, hangi CimSessions'ların bağlı olduğunu ve hangi protokolleri kullandıklarını görmek için kullanılır.

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

Önceden oluşturulan CimSessions'ların her ikisini de alın ve $CimSession adlı bir değişkende saklayın.

$CimSession = Get-CimSession

Biri WSMan protokolünü kullanarak, diğeri DCOM'u kullanarak her iki bilgisayarı da tek komutla sorgulayın.

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

WMI ve CIM cmdlet'leri hakkında çok sayıda blog makalesi yazdım. En kullanışlı olanlardan biri, WSMan'ın mı yoksa DCOM'un mu kullanılması gerektiğini otomatik olarak belirlemek ve hangisinin manuel olarak belirlenmesine gerek kalmadan CIM oturumunu otomatik olarak ayarlamak için oluşturduğum bir fonksiyonla ilgili. Bu blog makalesinin başlığı Dcom'a Geri Dönüş ile Uzak Bilgisayarlara CimSessions Oluşturmak için PowerShell İşlevi'dir.

CIM oturumlarıyla işiniz bittiğinde Remove-CimSession cmdlet'ini kullanarak bunları kaldırmalısınız. Tüm CIM oturumlarını kaldırmak için Get-CimSession'u Remove-CimSession'a yönlendirmeniz yeterlidir.

Get-CimSession | Remove-CimSession

Özet

Bu bölümde, hem yerel hem de uzak bilgisayarlarda WMI ile çalışmak için PowerShell'i kullanmayı öğrendiniz. Ayrıca, hem WSMan hem de DCOM protokolüne sahip uzak bilgisayarlarla çalışmak için CIM cmdlet'lerini nasıl kullanacağınızı da öğrendiniz.

Gözden geçirmek

  1. WMI ve CIM cmdlet'leri arasındaki fark nedir?
  2. Varsayılan olarak Get-CimInstance cmdlet'i hangi protokolü kullanır?
  3. Get-CimInstance ile bilgisayar adı belirtmek yerine CIM oturumu kullanmanın yararlarından bazıları nelerdir?
  4. Get-CimInstance ile kullanmak için varsayılan protokol dışında alternatif bir protokolü nasıl belirlersiniz?
  5. CIM oturumlarını nasıl kapatırsınız veya kaldırırsınız?

Önerilen Okuma

  • about_WMI
  • about_WMI_Cmdlet'ler
  • about_WQL
  • CimCmdlets Modülü
  • Video: CIM Cmdlet'lerini ve CIM Oturumlarını Kullanma

İlgili makaleler