Przedstawiamy kolejny odcinek cyklu "WMI jako obiektowa baza danych": Tym razem zajmiemy się praktycznymi zastosowaniami WMI, czyli skryptami.
1. Automatyzacja zarządzaniem systemami Windows
Mając do dyspozycje tak potężne narzędzie, jakim jest WMI, ciężko znaleźć dla niego jedno standardowe zastosowanie. Mimo wszystko jak sama nazwa produktu sugeruje (Windows Management Instrumentation – Instrumentacja Zarządzania Windows), znajdzie się ono w szerokiej grupie aplikacji kontrolujących i monitorujących systemy operacyjne wyprodukowane przez firmę Microsoft.
2. Przykładowe użycia
Aby jak najlepiej zobrazować uniwersalność rozwiązania, jakim jest WMI, przedstawione zostanie dziesięć problemów. Ich rozwiązania osadzono wewnątrz trzech środowisk uruchomieniowych: VBScript, PowerShell oraz WMIC. W większości przypadków istniej opcja użycia alternatywnych narzędzi do wykonania poniższych zadań, lecz stosowanie w każdy przypadku WMI pozytywnie wpływa na ujednolicenie mechanizmów zarządzania infrastrukturą. Sama lista problemów prezentuje się następująco:
2.1. Pobrać nazwę domeny, do której należy komputer.
W tym przypadku mamy do czynienia z pobieraniem informacji z klasy Win32_ComputerSystem i jego atrybutu o nazwie Domain.
2.1.1. VBScript
| strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
Set colSettings = objWMIService.ExecQuery _
("Select * from Win32_ComputerSystem")
For Each objComputer in colSettings
Wscript.Echo "System Name: " & objComputer.Name
Wscript.Echo "Domain: " & objComputer.Domain
Next
|
Listing: Pobrać nazwę domeny do której należy komputer – VBS
2.1.2. Powershell
Get-WmiObject Win32_ComputerSystem |select Name,Domain
2.1.3. WMIC
wmic COMPUTERSYSTEM get name, domain
2.2. Znaleźć nieprawidłowo działające urządzeia na danej maszynie.
Podstawą rozwiązania tego problemu jest enumeracja obiektów klasy Win32_PnPEntity, o atrybucie ConfigManagerErrorCode różnym od zera.
2.2.1. VBScript
| strComputer = "."
Set objWMIService = GetObject(_
"winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery _
("Select * from Win32_PnPEntity " _
& "WHERE ConfigManagerErrorCode <> 0")
For Each objItem in colItems
Wscript.Echo "Class GUID: " & objItem.ClassGuid
Wscript.Echo "Description: " & objItem.Description
Wscript.Echo "Device ID: " & objItem.DeviceID
Wscript.Echo "Manufacturer: " & objItem.Manufacturer
Wscript.Echo "Name: " & objItem.Name
Wscript.Echo "PNP Device ID: " & objItem.PNPDeviceID
Wscript.Echo "Service: " & objItem.Service
Next
|
Listing: Znaleźć nieprawidłowo działającyce urządzenia na danej maszynie - VBS
2.2.2. Powershell
Get-WmiObject Win32_PnPEntity -Filter "ConfigManagerErrorCode <> 0"|select ClassGuid, Description, DeviceID, Manufacturer, Name, PNPDeviceID, Service
2.2.3. WMIC
wmic path win32_PnPEntity WHERE "ConfigManagerErrorCode <> 0" get ClassGuid, Description, DeviceID, Manufacturer, Name, PNPDeviceID, Service
2.3. Znaleźć wersję Microsoft Office.
Rozwiązania tego problemu należy szukać w klasie Win32_Product.
2.3.1. VBScript
| strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
Set colSoftware = objWMIService.ExecQuery(_
"Select * from Win32_Product " & _
"Where Name Like" _
& " 'Microsoft Office%'")
For Each objItem in colSoftware
Wscript.Echo "Name: " & objItem.Name
Wscript.Echo "Version: " & objItem.Version
Next
|
Znaleźć wersję Microsoft Office - VBS
2.3.2. Powershell
Get-WmiObject win32_product -Filter "Name Like 'Microsoft Office%'"|select name, version
2.3.3. WMIC
WMIC posiada alias PRODUCT, który jest skrótem do zapytania SELECT * From Win32_Product. W związku z tym można wynik odpowiednio odfiltrować bez odnoszenia się do pełnej ścieżki klasy.
wmic PRODUCT where "name LIKE 'Microsoft Office%'" get name, version
2.4. Sprawdzić aktualny czas na komputerze.
Rozwiązania tego przypadku można upatrywać w klasie Win32_LocalTime i jej atrybutach.
2.4.1. VBScript
| strComputer = "."
Set objWMIService = GetObject( _
"winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery( _
"Select * from Win32_LocalTime")
For Each objItem in colItems
Wscript.Echo "Day: " & objItem.Day & VBNewLine _
& "Day Of Week: " & objItem.DayOfWeek & VBNewLine _
& "Hour: " & objItem.Hour & VBNewLine _
& "Minute: " & objItem.Minute & VBNewLine _
& "Month: " & objItem.Month & VBNewLine _
& "Quarter: " & objItem.Quarter & VBNewLine _
& "Second: " & objItem.Second & VBNewLine _
& "Week In Month: " & objItem.WeekInMonth & VBNewLine _
& "Year: " & objItem.Year
Next
|
Listing 11. Sprawdzić aktualeny czas na komputerze - VBS
2.4.2. Powershell
Get-WmiObject Win32_LocalTime | select Day, DayOfWeek, Hour, Milliseconds, Minute, Month, Quarter, Second, WeekInMonth, Year
2.4.3. WMIC
wmic path win32_localtime get Day, DayOfWeek, Hour, Milliseconds, Minute, Month, Quarter, Second, WeekInMonth, Year
2.5. Sprawdzić listę programów automatycznie uruchamianych przy starcie komputera.
W poniższym przykładzie z pomocą przychodzi klasa Win32_StartupCommand przechowująca informacje o wszystkich automatycznie startujących procesach.
2.5.1. VBScript
| strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
Set colStartupCommands = objWMIService.ExecQuery _
("Select * from Win32_StartupCommand")
For Each objStartupCommand in colStartupCommands
Wscript.Echo "Command: " _
& objStartupCommand.Command & VBNewLine _
& "Description: " & objStartupCommand.Description & VBNewLine _
& "Location: " & objStartupCommand.Location & VBNewLine _
& "Name: " & objStartupCommand.Name & VBNewLine _
& "SettingID: " & objStartupCommand.SettingID & VBNewLine _
& "User: " & objStartupCommand.User
Next
|
Listing 12. Sprawdzić listę automatycznie uruchamianych programów przy starcie komputera - VBS
2.5.2. Powershell
Get-WmiObject Win32_StartupCommand| select Command, Description, Location, Name, SettingID, User
2.5.3. WMIC
wmic path Win32_StartupCommand get Command, Description, Location, Name, SettingID, User
2.6. Zdefragmentować dany dysk twardy.
Jako, że defragmentację wykonuje się na poziomie partycji lub woluminów, więc używana będzie klasa Win32_Volume.
2.6.1. VBScript
| strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" _
& strComputer & "\root\cimv2")
Set colVolumes = objWMIService.ExecQuery _
("Select * from Win32_Volume Where Name = 'K:\\'")
For Each objVolume in colVolumes
errResult = objVolume.Defrag()
Next
|
Listing 13. Zdefragmentować dysk twardy - VBS
2.6.2. Powershell
(Get-WmiObject win32_volume -Filter "Name = 'K:\\'").invokemethod("Defrag",$Null)
2.6.3. WMIC
wmic path win32_volume where "Name = 'K:\\'" call defrag
2.7. Skasować zawartość logu aplikacyjnego na maszynie.
Zastosowane tutaj zostanie klasa Win32_NTLogEvent, która przechowuje informacje na temat logów systemu Windows.
2.7.1. VBScript
| strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate,(Backup)}!\\" & _
strComputer & "\root\cimv2")
Set colLogFiles = objWMIService.ExecQuery _
("Select * from Win32_NTEventLogFile " _
& "Where LogFileName='Application'")
For Each objLogfile in colLogFiles
objLogFile.ClearEventLog()
WScript.Echo "Cleared application event log file"
Next
|
Listing 14. Skasować zawartość logu aplikacyjnego na maszynie - VBS
2.7.2. Powershell
(Get-WmiObject Win32_NTEventLogFile -Filter "LogFileName = 'Application'").InvokeMethod("ClearEventLog",$Null)
2.7.3. WMIC
wmic path win32_NTEventLogFile where "LogFileName = 'Application'" call ClearEventLog
2.8. Stworzyć katalog współdzielony.
Metody do tworzenia nowych katalogów współdzielonych dostarcza klasa Win32_Share
2.8.1. VBScript
| Const FILE_SHARE = 0
Const MAXIMUM_CONNECTIONS = 25
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
Set objNewShare = objWMIService.Get("Win32_Share")
errReturn = objNewShare.Create _
("C:\Finance", "FinanceShare", FILE_SHARE, _
MAXIMUM_CONNECTIONS, _
"Public share for the Finance group.")
|
Listing 15. Stworzyć katalog współdzielony - VBS
2.8.2. Powershell
$parameters = $Null, "Finance Department share", 100, "FinanceShare", "", "C:\Finance", 0
Invoke-WmiMethod -class Win32_share -name create -ArgumentList $parameters
2.8.3. WMIC
wmic class win32_share call create $Null, "Finance Department share", 100, "FinanceShare", "", "C:\Finance", 0
2.9. Ustawić stały adres IP na interfejsie sieciowym.
Wszystkie ustawienia sieciowe są dostępne w klasie Win32_NetworkAdapterConfiguration i można je modyfikować poprzez zestaw zdefiniowanych metod.
2.9.1. VBScript
| strComputer = "."
Set objWMIService = GetObject( _
"winmgmts:\\" & strComputer & "\root\cimv2")
Set colNetAdapters = objWMIService.ExecQuery _
("Select * from Win32_NetworkAdapterConfiguration " _
& "where IPEnabled=TRUE")
strIPAddress = Array("10.2.2.27")
strSubnetMask = Array("255.0.0.0")
strGateway = Array("10.0.1.2")
strGatewayMetric = Array(1)
For Each objNetAdapter in colNetAdapters
errEnable = objNetAdapter.EnableStatic( _
strIPAddress, strSubnetMask)
errGateways = objNetAdapter.SetGateways(_
strGateway, strGatewaymetric)
Next
|
Listing 16. Ustawić stały adres IP na interfejsie sieciowym - VBS
2.9.2. Powershell
[Array] $ip = "10.2.2.27"
[Array] $mask = "255.0.0.0"
[Array] $gateway = "10.0.1.2"
[Array] $metric = 1
(Get-WmiObject Win32_NetworkAdapterConfiguration -Filter "IPEnabled=TRUE").InvokeMethod("EnableStatic", $ip, $mask)
Get-WmiObject Win32_NetworkAdapterConfiguration -Filter "IPEnabled=TRUE").InvokeMethod("SetGateways", $gateway, $metric)
2.9.3. WMIC
WMIC w standardzie ma zdefiniowany alias NICCONFIG, który jest skrótem do SELECT * FROM Win32_NetworkAdapterConfiguration.
WMIC NICCONFIG WHERE IPEnabled=TRUE CALL EnableStatic ("10.2.2.27"), ("255.0.0.0")
WMIC NICCONFIG WHERE IPEnabled=TRUE CALL SetGateways ("10.0.1.2"), (1)
2.10. Znaleźć listę usług wymaganych do uruchomienia usługi WMI.
Tym razem rozwiązaniem problemu jest enumeracja klas powiązanych z instancją klasy {Win32_Service.Name='winmgmt'}, gdzie pozostaje ona w roli zależnej (Dependent)
2.10.1. VBScript
| strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\"_
& strComputer & "\root\cimv2")
Set colServiceList = _
objWMIService.ExecQuery("Associators of " _
& "{Win32_Service.Name='winmgmt'} Where " _
& "AssocClass=Win32_DependentService " _
& "Role=Dependent" )
For Each objService in colServiceList
Wscript.Echo "Name: " & objService.Name _
& VBTab & "Display Name: " & objService.DisplayName
Next
|
Listing 17. ZNaleźć listę usług wymaganych do uruchomienia usługi WMI - VBS
2.10.2. Powershell
Get-WmiObject -Query "Associators of {Win32_Service.Name='winmgmt'} Where AssocClass=Win32_DependentService Role=Dependent"|select name, DisplayName
2.10.3. WMIC
wmic service where "name = 'winmgmt'" assoc /ASSOCCLASS:Win32_DependentService /RESULTROLE:Antecedent
3. Filtry WMI w GPO
Jednym z podstawowych mechanizmów zarządzania komputerami i użytkownikami w domenie Active Directory są Zasady Grupowe (Group Policy). Pozwalają one stosować zbiór ustawień na obiektach użytkowników i komputerów. Standardowo jest dostarczone klika mechanizmów filtrowania nakładania polis:
O ile dwa pierwsze nie są istotne z punktu widzenia tej pracy, o tyle trzeci zostanie poruszony.
Każdy obiekt filtra WMI może zawierać jedno lub więcej zapytań WMI. Jeśli taki filtr został przypisany do GPO, to polisa przed zastosowaniem ustawień, z ewaluuje wszystkie powiązane zapytania WQL. Jeśli któryś z nich nie zwróci żadnego wiersza, to ustawienia z obiektu polis nie zostaną zastosowane.
Typowymi zastosowaniami tego rozwiązania są między innymi:
- Nakładanie ustawień tylko na komputery danego producenta (klasa Win32_ComputerSystem, atrybut Manufacturer)
- Wywoływanie instalacji oprogramowania na maszynach gdzie nie ma jego nowszej wersji (klasa Win32_Product)
- Instalacja oprogramowania na komputerach, które mają wystarczającą ilość miejsca na dysku (klasa Win32_LogicalDisk)
- Wpisanie wartości rejestru tylko na danej wersji systemu operacyjnego (klasa Win32_OperatingSystem)
Podsumowanie
Jak widać WMI to bardzo potężne i szeroko stosowane rozwiązanie. Rozszerzalność, otwartość i łatwość dostępu do przechowywanych danych decyduje o wykorzystywaniu Microsoftowej implementacji standardów Distributed Managememnt Task Force w największych i najlepszych produktach służących do wspomagania procesów zarządzania informatyczną. Nieważne, czy jest to najnowsza wersja produktu zarządzającego maszynami wirtualnymi, czy też może oprogramowanie do inwentaryzacji sprzętu i oprogramowania w organizacji, lub też może zaawansowany monitor zdrowia komputerów, wszyscy korzystają z WMI jako źródła i repozytorium krytycznych danych.
WMI jako obiektowa baza danych: Wprowadzenie (1/6)
WMI jako obiektowa baza danych: Budowa WMI (2/6)
WMI jako obiektowa baza danych: narzędzia dostępu do danych (3/6)
WMI jako obiektowa baza danych: WQL (4/5) (publikacja 14. czerwca 2011)
WMI jako obiektowa baza danych: praktyczne zastosowanie WMI (5/6) (publikacja 16. czerwca 2011)
WMI jako obiektowa baza danych: pliki MOF (6/6) (publikacja 21. czerwca 2011)
Autor:
Daniel Stefaniak
(MVP, MCT, MCITP, MCTS, MCSA, MCP, CCNA)
Administrator, trener i inżynier systemowy. Członek SEClub oraz jeden z liderów Polskiej Grupy System Center. Aktywnie pisze na blogach http://www.w-files.pl oraz http://blogs.technet.com/plsc/.
MVP w kategorii Management Infrastructure