Die Registry und WMI
1 Einleitung
2 Bearbeiten der Registry
2.1 StdRegProv
Beispiel 1: Untersuchen der Klasse "Root\default:StdRegProv"
Beispiel 2: Erstellen eines Keys und einiger Werte
Beispiel 3: Auslesen einzelner RegistryWerte
Beispiel 4: Ändern vorhandener Registrywerte
Beispiel 5: Löschen eines einzelnen Wertes oder eines ganzen Keys
Beispiel 6a: Auflisten aller Werte eines Keys (Methode EnumValues)
Beispiel 6b: Ausgabe eines bestimmten Wertes (Methode EnumValues)
2.2 Win32_Registry
Beispiel 1: Allgemeine Informationen über die Registry
Die Registry und WMI
1 Einleitung
Auf das Thema WMI bin ich im Kapitel Grundlagen -> Automation Interfaces -> WMI wesentlich genauer eingegangen.
WMI besitzt zwei Klassen, mit denen auf die Regsitry lokal oder remote zugegriffen werden kann.
-
StdRegProv: Mit dieser Klasse können Registryeinträge lokal oder remote gelesen und geschrieben werden -
Win32_Registry: Mit dieser Klasse können einige Informationen lokal oder remote ausgelesen werden
Auch bei Zugriffen mit WMI braucht man immer den entsprechenden RootKey, um auf einen Subkey und letztlich auf den Wert mit seinen Daten zugreifen zu können. Bei WMI werden die RootKeys mit Zahlen angegeben:
The following trees are defined in Winreg.h.
HKEY_CLASSES_ROOT (2147483648 (0x80000000))
HKEY_CURRENT_USER (2147483649 (0x80000001))
HKEY_LOCAL_MACHINE (2147483650 (0x80000002))
HKEY_USERS (2147483651 (0x80000003))
HKEY_CURRENT_CONFIG (2147483653 (0x80000005))
HKEY_DYN_DATA (2147483654 (0x80000006))
[Quelle]: msdn.microsoft.com/en-us/library/windows/desktop/aa390388%28v=vs.85%29.aspx
- MSDN: StdRegProv class
- MSDN: Win32_Registry class
Für die Registry bietet natürlich auch WMI einige Möglichkeiten an, deren Hauptvorteil gegenüber dem PowershellregistryProvider die einfache Remotefähigkeit ist.
Die wichtigste Klasse ist die StdRegProv-Klasse aus dem WMI-Namespace "root/default". Da dieser Namespace im Normalfall nicht der StandardNamespace eines Windowsrechners ist, muss dieser beim Aufruf der Klasse explizit mit angegeben werden. Über WMI-Namespaces findet ihr im Kapitel Grundlagen -> Automation Intefaces ->
Eine kleine zusätzliche Hürde ist die Erstellung einer Instanz aus der Klasse StdRegProv. Eine Instanz wird nicht mit der sonst bei WMI-Klassen üblichen Syntax erzeugt -Beispiele findet ihr unter
Beispiel 1: Untersuchen der Klasse "Root\default:StdRegProv"
Set-StrictMode -Version "2.0" Clear-Host $Computer = "." $WMI = [wmiclass]"\\$computer\root\default:stdRegProv" #$WMI = new-object System.Management.ManagementClass "\\$Computer\Root\default:StdRegProv" $WMI.Methods | Format-Wide {$_.Name} -Column 4 |
#Ausgabe CreateKey DeleteKey EnumKey EnumValues DeleteValue SetDWORDValue SetQWORDValue GetDWORDValue GetQWORDValue SetStringValue GetStringValue SetMultiStringValue GetMultiStringValue SetExpandedStringValue GetExpandedStringValue SetBinaryValue GetBinaryValue CheckAccess SetSecurityDescriptor GetSecurityDescriptor |
Mit diesen Methoden kann man nun nach Herzenslust auf die lokale Registry, ebenso wie auf die Registry eines Remoterechners zugreifen.
Beispiel 2: Erstellen eines Keys und einiger Werte
Set-StrictMode -Version "2.0" Clear-Host $Computer = "." $WMI = New-Object System.Management.ManagementClass "\\$Computer\Root\default:StdRegProv" #$WMI = [WmiClass]"\\$Computer\root\default:stdRegProv" $HKCU = 2147483649 #weitere Werte stehen zu Beginn des Kapitel 2 #Key erstellen $Key = "Software\_MyNewKey" $Result = $WMI.CreateKey($HKCU,$Key) #DWordValue anlegen $ValueName = "MyDWord" [Int32]$Data = 31 #Ohne Typangabe der Variable gibt es eine Fehlermeldung $Result=$WMI.SetDWordValue($HKCU,$Key,$ValueName,$Data) #Result.Returnvalue #StringValue anlegen $ValueName = "MyString" [String]$Data = "Mein Freund Karl Napf" #Ohne Typangabe der Variable gibt es eine Fehlermeldung $Result = $WMI.SetStringValue($HKCU,$Key,$ValueName,$Data) #MultiStringValue anlegen $ValueName = "MyMultiString" [String[]]$Datas = @() #nicht auf einen Datentyp festgelegt ist: $arrData=@() $Datas = "Karl_Napf","Franz_Ferdinand", "Tom_Turbo" $Result = $WMI.SetMultiStringValue($HKCU,$Key,$ValueName,$Datas) #ExpandStringValue anlegen $ValueName = "MyExpandString" [String]$Data = "%temp%" $Result = $WMI.SetExpandedStringValue($HKCU,$Key,$ValueName,$Data) #BinaryValue anlegen $ValueName = "MyBinaryString" [Byte[]]$Data = 0x4D,0x5A,0x90,0x00,0x03 $Result=$WMI.SetBinaryValue($HKCU,$Key,$ValueName,$Data) |
Dieses Beispiel erzeugt unter dem HKCU\Software\_MyNewKey einige Werte unterschiedlichen Datentyps.
- MSDN: SetBinaryValue method of the StdRegProv Class (enthält die Werte der übrigen Rootkeys)
- Mit "$Result.ReturnValue -eq 0" könnte man überprüfen, ob die einzelnen Schritte erfolgreich durchgelaufen sind.
-
Im Kapitel
3.1 Zugriff auf die Registry (Remote oder Lokal) habe ich dieselbe Aufgabe mit .Net-Klassen gelöst
Beispiel 3: Auslesen einzelner RegistryWerte
Wenn ihr mit Beispiel 2 den BeispielKey angelegt habt, könnt ihr dieses Beispiel direkt hinterherschicken, um die zugehörigen Daten der Werte auszulesen. Je nach Wertetyp muss die passende Methode gewählt werden.
Set-StrictMode -Version "2.0" Clear-Host $Computer = "." #$WMI = new-object System.Management.ManagementClass "\\$Computer\Root\default:StdRegProv" $WMI = [WmiClass]"\\$Computer\root\default:stdRegProv" $HKCU = 2147483649 #weitere Werte stehen zu Beginn des Kapitel 2 $Key = "Software\_MyNewKey" #DWordValue auslesen $ValueName = "MyDWord" $Result=$WMI.GetDWordValue($HKCU,$Key,$ValueName) "`n" "DWord Dezimal: {0}" -f $Result.UValue "DWord Hex: {0:x} `n" -f $Result.UValue #StringValue auslesen $ValueName = "MyString" $Result=$WMI.GetStringValue($HKCU,$Key,$ValueName) "REG_SZ: {0} `n" -f $Result.SValue #MultiStringValue auslesen $ValueName = "MyMultiString" $Result = $WMI.GetMultiStringValue($HKCU,$Key,$ValueName) $Result.SValue | foreach{ "REG_MULTI_SZ: {0}" -f $_ } "`n" #ExpandStringValue auslesen $ValueName = "MyExpandString" $Result = $WMI.GetExpandedStringValue($HKCU,$Key,$ValueName) "REG_EXPANDED_SZ: {0} `n" -f $Result.SValue #BinaryValue auslesen $ValueName = "MyBinaryString" $Result = $WMI.GetBinaryValue($HKCU,$Key,$ValueName) "REG_BINARY" $Result.UValue |
#Ausgabe, wenn der Key HKCU\Software\_MyTestKey aus Beispiel 2 existiert DWord Dezimal: 31 DWord Hex: 1f REG_SZ: Mein Freund Karl Napf REG_MULTI_SZ: Karl_Napf REG_MULTI_SZ: Franz_Ferdinand REG_MULTI_SZ: Tom_Turbo REG_EXPANDED_SZ: C:\WINDOWS\TEMP REG_BINARY 77 90 144 0 3 |
Unter MSDN: StdRegProv class sind alle Methoden der Klasse StdRegProv aufgeführt
Im Beispiel 6b lasse ich WMI selbst den Datentyp bestimmen.
Beispiel 4: Ändern vorhandener Registrywerte
Wenn ihr mit Beispiel 2 den BeispielKey angelegt habt, könnt ihr dieses Beispiel direkt hinterherschicken, in dem vorhandene Werte verändert werden.
Set-StrictMode -Version "2.0" Clear-Host $Computer = "." #$WMI = New-Object System.Management.ManagementClass "\\$Computer\Root\default:StdRegProv" $WMI = [WmiClass]"\\$computer\root\default:stdRegProv" $HKCU = 2147483649 #weitere Werte stehen zu Beginn des Kapitel 2 $Key = "Software\_MyNewKey" #DWordValue ändern (+1) $ValueName = "MyDWord" $Result = $WMI.GetDWordValue($HKCU,$Key,$ValueName) "DWord alt Dezimal: {0}" -f $Result.UValue "DWord alt Hex: {0:x}" -f $Result.UValue [Int32]$Data = $Result.UValue+1 $Result = $WMI.SetDWordValue($HKCU,$Key,$ValueName,$Data) $Result = $WMI.GetDWordValue($HKCU,$Key,$ValueName) "DWord neu Dezimal: {0}" -f $Result.UValue "DWord neu Hex: {0:x} `n" -f $Result.UValue #StringValue ändern (Replace) $ValueName = "MyString" $Result=$WMI.GetStringValue($HKCU,$Key,$ValueName) [String]$Data=$Result.SValue "REG_SZ alt: {0} " -f $Result.SValue $Data=$Data.Replace("Karl Napf","Franz-Ferdinand") $Result=$WMI.SetStringValue($HKCU,$Key,$ValueName,$Data) $Result=$WMI.GetStringValue($HKCU,$Key,$ValueName) "REG_SZ neu: {0} `n" -f $Result.SValue #MultiStringValue verändern (Arrayelement hinzufügen) $ValueName = "MyMultiString" $Result = $WMI.GetMultiStringValue($HKCU,$Key,$ValueName) $Result.SValue | foreach{ "REG_MULTI_SZ alt: {0}" -f $_ } [string[]]$Datas = $Result.SValue $Datas += "Karl_Knall" $Result = $WMI.SetMultiStringValue($HKCU,$Key,$ValueName,$Datas) $Result = $WMI.GetMultiStringValue($HKCU,$Key,$ValueName) $Result.SValue | foreach{ "REG_MULTI_SZ neu: {0}" -f $_ } |
#Ausgabe DWord alt Dezimal: 31 DWord alt Hex: 1f DWord neu Dezimal: 32 DWord neu Hex: 20 REG_SZ alt: Mein Freund Karl Napf REG_SZ neu: Mein Freund Franz-Ferdinand REG_MULTI_SZ alt: Karl_Napf REG_MULTI_SZ alt: Franz_Ferdinand REG_MULTI_SZ alt: Tom _urbo REG_MULTI_SZ neu: Karl_Napf REG_MULTI_SZ neu: Franz_Ferdinand REG_MULTI_SZ neu: Tom_Turbo REG_MULTI_SZ neu: Karl_Knall |
Unter MSDN: StdRegProv class sind alle Methoden der Klasse StdRegProv aufgeführt
Beispiel 5: Löschen eines einzelnen Wertes oder eines ganzen Keys
Wenn ihr mit Beispiel 2 den BeispielKey angelegt habt, könnt ihr dieses Beispiel direkt hinterherschicken, indem ein Wert oder der gesamte Key gelöscht wird
Set-StrictMode -Version "2.0" Clear-Host $Computer = "." $WMI = New-Object System.Management.ManagementClass "\\$Computer\Root\default:StdRegProv" #$WMI = [wmiclass]"\\$computer\root\default:stdRegProv" $HKCU=2147483649 #weitere Werte stehen zu Beginn des Kapitel 2 $Value = "MyString" $Key = "Software\_MyNewKey" #Wert löschen $Result=$WMI.DeleteValue($HKCU,$Key,$Value) If($Result.ReturnValue -eq 0) { "Das Löschen des Wertes war erfolgreich" }else{ "Das Löschen des Wertes war nicht erfolgreich" } <# #Key löschen $Result = $WMI.DeleteKey($HKCU,$Key) If($Result.ReturnValue -eq 0) { "Das Löschen des Keys war erfolgreich" }else{ "Das Löschen des Keys war nicht erfolgreich" } #> |
#mögliche Ausgabe Das Löschen des Wertes war nicht erfolgreich |
Beispiel 6a: Auflisten aller Werte eines Keys (Methode EnumValues)
Wenn ihr mit Beispiel 2 den BeispielKey angelegt habt, könnt ihr dieses Beispiel direkt hinterherschicken, indem alle Werte eines Keys samt ValueType ausgelesen werden.
Set-StrictMode -Version "2.0" Clear-Host #Mögliche Werte der RegValueKinds als Hash $RegValueKinds = @{1 = "REG_SZ"; 2 = "REG_EXPAND_SZ"; 3 = "REG_BINARY" 4 = "REG_DWORD" 7 = "REG_MULTI_SZ" } $Computer="." $WMI = New-Object System.Management.ManagementClass "\\$Computer\Root\default:StdRegProv" #$WMI = [wmiclass]"\\$computer\root\default:stdRegProv" $HKCU=2147483649 #weitere Werte für andere RootKeys zu Beginn des Kapitels 2 $Key = "Software\_MyNewKey" #Hier werden alle Werte inkl. dem RegValueType unter dem Key in die Variable $Result gelesen $EnumValues=$WMI.EnumValues($HKCU,$Key) [String[]]$sNames=$EnumValues.sNames [Int[]]$Types=$EnumValues.Types #ab hier werden die Daten von jedem Value ausgelesen, abhängig vom Datentyp (=$Types[$i]) for($i=0;$i -lt $sNames.count;$i++){ switch($Types[$i]) { 1 {$Data=$WMI.GetStringValue($HKCU,$Key,$sNames[$i]) "{0} {1} {2}" -f $sNames[$i],$RegValueKinds.Get_Item($Types[$i]),$Data.SValue } 2 {$Data=$WMI.GetExpandedStringValue($HKCU,$Key,$sNames[$i]) "{0} {1} {2}" -f $sNames[$i],$RegValueKinds.Get_Item($Types[$i]),$Data.SValue } 3 {$Data=$WMI.GetBinaryValue($HKCU,$Key,$sNames[$i]) "{0} {1} {2}" -f $sNames[$i],$RegValueKinds.Get_Item($Types[$i]),[String]$Data.UValue } 4 {$Data=$WMI.GetDWordValue($HKCU,$Key,$sNames[$i]) "{0} {1} {2}" -f $sNames[$i],$RegValueKinds.Get_Item($Types[$i]),$Data.UValue } 7 {$Data=$WMI.GetMultiStringValue($HKCU,$Key,$sNames[$i]) "{0} {1} {2}" -f $sNames[$i],$RegValueKinds.Get_Item($Types[$i]),[String]$Data.sValue } default {"unbekannter Registrytyp"} } } |
#Ausgabe MyDWord REG_DWORD 32 MyString REG_SZ Mein Freund Franz-Ferdinand MyExpandString REG_EXPAND_SZ C:\WINDOWS\TEMP MyBinaryString1 REG_BINARY 77 90 144 0 3 MyMultiString REG_MULTI_SZ Karl Napf Franz Ferdinand Tom Turbo Karl Knall |
Kap2.1 StdRegProv Beispiel_6a.ps1.txt
Das Beispiel liefert dasselbe Ergebnis wie das .Net Beispiel 2a unter Kapitel 3.1.1 Lesen und Ändern von Registrywerten
Beispiel 6b: Ausgabe eines bestimmten Wertes (Methode EnumValues)
Wenn ihr mit Beispiel 2 den BeispielKey angelegt habt, könnt ihr dieses Beispiel direkt hinterherschicken, indem ein bestimmter Wert samt ValueType ausgelesen wirde.
Set-StrictMode -Version "2.0" Clear-Host Remove-Variable -scope script * -EA 0 #Mögliche Werte der RegValueKinds als Hash $RegValueKinds = @{1 = "REG_SZ"; 2 = "REG_EXPAND_SZ"; 3 = "REG_BINARY" 4 = "REG_DWORD" 7 = "REG_MULTI_SZ" } $Computer="." $WMI = New-Object System.Management.ManagementClass "\\$Computer\Root\default:StdRegProv" #$WMI = [wmiclass]"\\$computer\root\default:stdRegProv" $HKCU=2147483649 #weitere Werte für andere RootKeys zu Beginn des Kapitels 2 $Key = "Software\_MyNewKey" $Name = "MyMultiString" #Hier werden alle Werte inkl. dem RegValueType unter dem Key in die Variable $Result gelesen $EnumValues=$WMI.EnumValues($HKCU,$Key) [String[]]$sNames=$Enumvalues.sNames [Int[]]$Types=$EnumValues.Types for($i=0;$i -lt $sNames.count;$i++){ if($sNames[$i] -eq $Name){ switch($Types[$i]) { 1 {$Data=$WMI.GetStringValue($HKCU,$Key,$Name) "{0} {1} {2}" -f $Name,$RegValueKinds.Get_Item($Types[$i]),$Data.SValue } 2 {$Data=$WMI.GetExpandedStringValue($HKCU,$Key,$sNames[$i]) "{0} {1} {2}" -f $Name,$RegValueKinds.Get_Item($Types[$i]),$Data.SValue } 3 {$Data=$WMI.GetBinaryValue($HKCU,$Key,$sNames[$i]) "{0} {1} {2}" -f $Name,$RegValueKinds.Get_Item($Types[$i]),[string]$Data.UValue } 4 {$Data=$WMI.GetDWordValue($HKCU,$Key,$sNames[$i]) "{0} {1} {2}" -f $Name,$RegValueKinds.Get_Item($Types[$i]),$Data.UValue } 7 {$Data=$WMI.GetMultiStringValue($HKCU,$Key,$sNames[$i]) "{0} {1} {2}" -f $Name,$RegValueKinds.Get_Item($Types[$i]),[string]$Data.sValue } default {"unbekannter Registrytyp"} } #switch } #if } #for |
#Ausgabe MyMultiString REG_MULTI_SZ Karl_Napf Franz_Ferdinand Tom_Turbo |
Im Gegensatz zu Beispiel 3 lasse ich hier WMI selbst den Typ der Daten bestimmen und mit der entsprechenden Methode ausgeben.
WMI bringt mit Win32_Registry eine weitere RegistryKlasse mit, mit deren Hilfe man sich einige Informationen über die aktuelle Registry auslesen kann. Der Wert dieser Informationen hält sich meines Erachtens aber eher in Grenzen. Nichtsdestotrotz ein Beispiel, was man von dieser Klasse alles erfahren kann.
Beispiel 1: Allgemeine Informationen über die Registry
Set-StrictMode -Version "2.0" Clear-Host $Computer = "." $Namespace = "root\CIMV2" $Win32_Registry=Get-WmiObject -class Win32_Registry -computername $Computer -namespace $Namespace "Caption: {0}" -f $Win32_Registry.Caption "Computername: {0}" -f $Win32_Registry.__Server "aktuelle Größe in Mb: {0}" -f $Win32_Registry.CurrentSize "maximale Größe in Mb: {0}" -f $Win32_Registry.MaximumSize "Installationsdatum: {0:d}" -f $Win32_Registry.ConvertToDateTime(($Win32_Registry.InstallDate)) "Status: {0} " -f $Win32_Registry.Status |
#mögliche Ausgabe Caption: Registrierung Computername: Dom1Srv01 aktuelle Größe in Mb: 9 maximale Größe in Mb: 120 Installationsdatum: 14.04.2008 Status: OK |