1 Einleitung
 2 Struktur der Registry
 3 WerteTypen von Daten
      Beispiel 1: Auflisten der RegistryValueKinds
      Beispiel 2: Auslesen der Warnschwelle für den freien Plattenplatz
      Beispiel 3: Anzeigen der WindowsVersionsnummer auf dem Desktop
      Beispiel 4: Auslesen eines REG_EXPAND_SZ Wertes
      Beispiel 5: Auslesen eines REG_MULTI_SZ Wertes
      Beispiel 6a: einen Binärwert auslesen
      Beispiel 6b: einen Binärwert auslesen, Sonderzeichen entfernen und die verbleibenden Binärdaten in Ascii umwandeln
  4 Limits der Registry
 


1 Einleitung

Die Registry ist ein zentrales Element aller Windows Betriebssysteme seit Windows 95, dessen Handling sich für das PowershellSkripting wieder ganz besonders eignet.

Zu den alltäglichen Aufgaben eines Windowsadministrators gehört es, Registryeinträge zu prüfen, neu zu setzen, zu editieren oder zu löschen. Auf mehreren Maschinen wird dies ohne Automation schnell eine langwierige und fehleranfällige Angelegenheit, so dass sich die Investition an Zeit und Energie in ein geeignetes Skript schnell bezahlt macht.

Ebenso benötigen manche Skripte selbst bestimmte Registrywerte. Zu Beginn eines solchen Skriptes sollte der Programmierer daher die Existenz dieser Werte erstmal sicherstellen. 

2 Struktur der Registry

Jeder von Euch war natürlich schon in der Registry unterwegs und hat dort Einträge ausgelesen oder verändert.
Damit wir in den folgenden Kapiteln von denselben Dingen sprechen und die richtigen Bezeichnungen anwenden, will ich hier die Struktur der Registry mit ihren Elementen darstellen.

Der Screenshot stellt die deutsche Registry eines Windows7-Rechners dar. 

In dem Screenshot erkennt man die Elemente der Registry. 

A) Die großen Fünf (The Big Five)

HKEY_CURRENT_CONFIG  (HKCC)
HKEY_CLASSES_ROOT      (HKCR)
HKEY_CURRENT_USER      (HKCU)
HKEY_LOCAL_MACHINE    (HKLM)
HKEY_USERS                     (HKU)

sind die sogenannten "Rootkeys" oder "Subtrees" oder "Base Keys" der Registry. Sie zeichnen sich dadurch aus, dass sie keine ParentSubkeys besitzen.


B) SubKeys/ Registrypfad

Subkeys können aus einem einzigen Element oder einem ganzen Kette einzelner Subkeys bestehen. Eine Kette einzelner Subkeys samt einem Value wird oft als "Registrypfad" bezeichnet
Subkeys enthalten mindestens einen Wert (Value) und können darüber hinaus einen oder mehrere weitere, ihnen untergeordnete, Subkeys enthalten.


C) Values (Werte)

Values enthalten die Eigenschaften "Name", Typ" und "Daten".

- Der Name eines Values darf alle druckbaren Zeichen enthalten außer dem Backslash "\" und ist unabhängig von der verwendeten Windowssprachversion

- Der Typ des Values (=RegistryValueKind) ist abhängig, welche Daten er beinhaltet. Beim Programmieren muss man genau darauf achten, mit welchen Typen man es zu tun hat. So ist ein BinaryWert (Binary) oder ein MultiString (Multi_SZ) anders zu behandeln als ein einfacher String (Reg_SZ) oder eine Zahl (Reg_DWord).
MSDN: Registry Value Types 

- Die Daten selbst können abhängig von der Sprachversion des Windowssystems sein. Gemäß dem MSDN-Artikel im Kapitel "0.2 Limitierungen der Registry" sollten die Daten eines Wertes nicht größer 2 kB sein.

Es gibt noch zwei weitere wichtige Strukturelemente der Registry, die im Registryeditor nicht als solche zu erkennen sind.

D) Links 

Ebenso wie im Filesystem gibt es in der Registry Shortcuts, nur dass diese hier Links genannt werden und nicht wie im Filesystem, als solche mit einem speziellen Symbol gekennzeichnet sind. So ist der gesamte RootKey "HKEY_CURRENT_USER" nur ein Link des zugehörigen Users unter HKEY_USERS. 


E) Hives und Dateien

MSDN: Registry Hives

Unter dem Subkey "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\hivelist" werden die Hives der Registry aufgelistet.

Auf den ersten Blick sieht die Registry im Registryeditor so aus, als sei sie eine einzige große, konstante Datensammlung. Das ist so nicht richtig, sondern die Registry besteht zum einen Teil aus statischen Daten, die in verschiedenen Dateien im Filesystem abgelegt sind und zum anderen Teil aus dynamischen Daten, die bei jedem Systemstart neu generiert werden.

Das folgende Bild zeigt die Hives mit ihrem zugehörigen Registrypfad auf der linken Seite in der Spalte "Name" und den Pfad zur zugehörigen Datei im Filesystem in der Spalte "Daten". 
Der Dateipfad wird nicht über einen Laufwerksbuchstaben identifiziert, sondern über die Festplatte und deren Partition. Üblicherweise liegen die Registrydateien immer unter "C:\Windows\System32\config".
Hier nicht aufgeführte Registrypfade sind entweder dynamisch oder Links (siehe unten)

 

3 WerteTypen von Daten

Wie im letzten Kapitel "0.1.1 Struktur der Registry" im Abschnitt C) beschrieben, können Registrywerte verschiedene Datentypen besitzen. Je nach Typ erfordern RegistryWerte eine etwas andere Behandlung.

Dieses Kapitel soll einen Überblick über die verschiedenen Wertetypen mit ein paar einfachen Beispielen geben. 

MSDN: RegistryValueKind Enumeration                               

Member name 

Description

String 

A null-terminated string. This valueis equivalent to the Win32 API registry data type REG_SZ.

ExpandString 

A null-terminated string that contains unexpanded references to environment variables, such as %PATH%, that are expanded when the value is retrieved. This value is equivalent to the Win32 API registry data type REG_EXPAND_SZ.

Binary

Binary data in any form. This value is equivalent to the Win32 API registry data type REG_BINARY. 

DWord

A 32-bit binary number. This value is equivalent to the Win32 API registry data type REG_DWORD.

MultiString

An array of null-terminated strings, terminated by two null characters. This value is equivalent to the Win32 API registry data type REG_MULTI_SZ.

QWord

A 64-bit binary number. This value is equivalent to the Win32 API registry data type REG_QWORD.

 

Unknown

An unsupported registry data type. For example, the Microsoft Win32 API registry data type REG_RESOURCE_LIST is unsupported. Use this value to specify that the  SetValue method should determine the appropriate registry data type when storing a name/value pair.

Das Kürzel "SZ" bei den Stringtypen steht übrigens für StringZero, also nullterminated


Beispiel 1: Auflisten der RegistryValueKinds

[Enum]::GetValues([Microsoft.Win32.RegistryValueKind])
#Ausgabe

Unknown
String
ExpandString
Binary
DWord
MultiString
QWord


A)  Der Datentyp DWord / QWord

DWord ist der häufigste Datentyp innerhalb der Registry. Er kann Integerwerte zwischen 0 und 2^32 (=etwa 4,29 Millionen) enthalten. 
DWords werden besipielsweise für Boolsche Werte (0 oder 1), Prozentangaben (0 bis 100) oder Zeitangaben, die oft in Millisekunden vorliegen, benutzt.
Entsprechend kann der Datentyp QWord Integerwerte bis zu 2^64 aufnehmen. Dieser Wert kommt im täglichen Leben kaum vor. 

Hier sind zwei kleine Beispiele für RegistryWerte vom Typ DWord. Für einen flächendeckenden Einsatz dieser Werte sind GPOs/ GPPs natürlich besser geeigent als ein Skript.

 

Beispiel 2: Auslesen der Warnschwelle für den freien Plattenplatz

Set-StrictMode -Version "2.0"
Clear-Host
 

$Key = "HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters"
$Wert = "DiskSpaceThreshold" # $Key und $Wert sind nicht casesesitiv

If(Test-Path -Path $Key){  #Existenzprüfung des Keys
  If ((Get-ItemProperty $Key).$Wert -ne $null){ #Existenzprüfung des Wertes
    "Dezimal:     {0}" -f (Get-ItemProperty $Key).$Wert
    "Hexadezimal: {0:x}" -f (Get-ItemProperty $Key).$Wert
  }Else{
    "Der Wert $Wert ist nicht vorhanden"
  } 
}Else{
"Der Key $Key ist nicht vorhanden"
}

#mögliches Ergebnis

Dezimal:     10
Hexadezimal: a

 

Technet: DiskSpaceThreshold
 

Beispiel 3: Anzeigen der WindowsVersionsnummer auf dem Desktop

Set-StrictMode -Version "2.0"
Clear-Host
 

$Key="HKCU:\Control Panel\Desktop"
$Wert="PaintDesktopVersion" #Range 0 | 1

Set-ItemProperty -Path $Key -Name PaintDesktopVersion -Value 1

Technet: PaintDesktopVersion

  • Existiert dieser Wert bereits und hat den richtigen Typ, was bei PaintDesktopVersion, default der Fall ist, so kann man auf diese Weise einfach den Wert verändern. 
  • Existiert der Wert nicht, so würde bei dieser Programmierweise kein DWord geschrieben, sondern ein String.

Ergebnis:

Unter dem Key "HKCU:\Control Panel\Desktop" liegen viele weitere Einstellungen, die den Desktop des Users betreffen, wie für das Hintergrundbild oder den Bildschirschoner

Technet: Desktop

 
B) Der Datentyp String REG_SZ

Nach DWord ist REG_SZ der nächst häufigste Datentyp. "SZ" in Reg_SZ bedeutet in der ungarischen Notation übrigens "string terminated with a zero byte". 

Stringwerte sind sehr flexibel. Dort können lesbare Werte wie Versionsnummern, Konfiguarationsparameter und vieles mehr gespeichert werden.
Der Wertebereich ist nicht auf ASCII-Zeichen beschränkt, so dass StringWerte auch deutsche Umlaute oder japanische Zeichen (Unicode) enthalten können.

Ein Beispiel für einen REG_SZ Wert ist, denke ich, an dieser Stelle nicht nötig. 


C) Der Datentyp Expandstring REG_EXPAND_SZ

Umgebungsvariablen stellen eine Reihe von Informationen des Betriebssystems und des Userprofiles direkt als Variable zur Verfügung. 
siehe Kapitel "NTFS-Filesystem -> Pfade -> 1.1.1.2 Umgebungsvariablen - Environment Variables"

Werden Umgebungsvariablen in der Regsitry verwendet, so stehen diese als Datentyp REG_EXPAND_SZ in der Registry

Als Beispiel sei hier der Registryhive "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" mit den Werten "Temp " und "Tmp" gezeigt. In diesem Hive sind die Umgebungsvariablen hinterlegt, gleichzeitig werden diese hier schon benutzt.

 

Beispiel 4: Auslesen eines REG_EXPAND_SZ Wertes

Set-StrictMode -Version "2.0"
Clear-Host

 
$Key = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
$Wert = "Temp" # $Key und $Wert sind nicht casesesitiv
(Get-ItemProperty $Key).$Wert
Ergebnis

C:\WINDOWS\TEMP

Da die Daten des Wertes "Temp" vom Typ "REG_EXPAND_SZ" sind, interpretiert Powershell den Teilsstring %Systemroot% als Umgebungsvariable und expandiert diese.
Wäre "%SystemRoot%\Temp" in einer normalen Stringvariablen abglegt, so wäre das Ergebnis sozusagen unexpandiert, also "%SystemRoot%\Temp" 


D) Der Wertetyp MultiString REG_MULTI_SZ

Manchmal soll eine Gruppe von zusammengehörigen Daten in einem Wert gespeichert werden. Teilweise geschieht dies in REG_SZ Werten, in denen die Daten als durch ";" getrennte Substrings aufgeführt sind. 
Manchmal werden solche Daten aber auch als Arrays in Werten vom Typ REG_EXPAND_SZ gespeichert.

Ein Beispiel dafür ist der REG_EXPAND_SZ Wert "SystemBiosVersion" unter "HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System". Unter diesem Wert befinden sich Information über den Biosnamen, sowie das BiosAlter.

 

Beispiel 5: Auslesen eines REG_MULTI_SZ Wertes

Set-StrictMode -Version "2.0"
Clear-Host

 
$Key = "HKLM:\HARDWARE\DESCRIPTION\System"
$Value = "SystemBiosVersion" # $Key und $Wert sind nicht casesesitiv
$MultiSZDatas = @((Get-ItemProperty $Key).$Wert)
$MultiSZDatas 
#Ausgabe

VRTUAL - 3000919
BIOS Date: 03/19/09 22:51:32  Ver: 09.00.04
BIOS Date: 03/19/09 22:51:32  Ver: 09.00.04

Man sieht, dass dieser Rechner ein virtuelles BIOS besitzt. Anhand der Versionsnummer kann man sogar den Virtualisierer auf dem Host bestimmen. (siehe das Kapitel WMI -> 4.2 Informationen zum Betriebssystem -> Beispiel 2b)


E) Der Datentyp Binary REG_BINARY

Binarydaten sind am schwierigsten zu behandeln. Zum Einen bestehen Binarydaten nicht aus lesbaren Buchstaben oder Zahlen, sondern aus den zugehörigen ASCII-Zahlen, zum anderen enthalten Binarydaten oft viele ASCIIZeichen < 32, also nicht llesbare Zeichen. Zeilenumbrüche wiederum können manchmal durchaus die Leserlichkeit der Ausgabe erhöhen, manchmal sind sie wieder unerwünscht. 
Man muss ausprobieren, mit welchem Algorithmus man einem bestimmten REG_BINARY Wert seinen Inhalt jeweils am geeignetesten entlocken kann. 

Beispiel 6a: einen Binärwert auslesen

Set-StrictMode -Version "2.0"
Clear-Host 
Remove-Variable * -EA 0 

$Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections"
$BinaryDatas = ((Get-ItemProperty $Path -Name DefaultConnectionSettings).DefaultConnectionSettings)
$BinaryDatas | ForEach{
    $BinaryOut+=" "+$_.Tostring() 
  }
$BinaryOut
#Ausgabe gekürzt

70 0 0 0 3 0 0 0 11 0 0 0 90 0 0 0 102 116 112 61 77 121 70 84 80 80 114 111 120 121 58 56 48 56 51 59 104 116 116 112 61 77 121 72 84 84 80 80 114 111 120 121 58 56 48 56 49 59 104 116 116 112 115 61 77 121 83 101 99 117 114 101 80 114 111 120 121 58 56 48 56 50 59 115 111 99 107 115 61 77 121 83 99 111 107 115 80 114 111 120 121 58 56 48 56 52 17 0 0 0 49 48 46 49 48 46 49 46 50 59 49 57 50 46 49 54 57 0 0 0 0 4 0 0 0

Mehr als zu erkennen, dass der Wert exisitiert und binäre Daten enthält, vermag man diesem Ergebnis nicht zu entnehmen.


Beispiel 6b: einen Binärwert auslesen, Sonderzeichen entfernen und die verbleibenden Binärdaten in Ascii umwandeln

Set-StrictMode -Version "2.0"
Clear-Host  
Remove-Variable * -EA 0

$Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections"
$BinaryDatas = @((Get-ItemProperty $Path -Name "DefaultConnectionSettings").DefaultConnectionSettings)

#Im Folgenden werden alle Ascii-Zeichen zwischen 0 und 11 aus dem String entfernt. Diese Zeichen sind keine lesbaren Zeichen
$BinaryDatas | foreach{
if (($_ -ge "12") -and ($_ -lt "127")){ 
   $OnlyReadableASCII += [char]$_ 
   }#if
}#foreach
 
$OnlyReadableASCII
#Ausgabe

FZftp=MyFTPProxy:8083;http=MyHTTPProxy:8081;https=MySecureProxy:8082;socks=MySocksProxy:808410.10.1.2;192.169ph
wzn-&?
WM de-DE^y-&?WM

In dieser Ausgabe kann man erkennen, dass in dem Registrywert die LAN-Einstellungen wie Proxyadressen und Ausnahmelisten des Internetexplorers hinterlegt sind.

Oft sind Binarydaten in der Regsitry verschlüsselt. Dann wird man natürlich keinen sinnvollen Text erhalten. 

 

4 Limits der Registry

MSDN: Registry Storage Space

Für das Scripting selbst ist dieser Artikel nicht wichtig. Mögliche Grenzen seines Systems zu kennen, ist denke ich dennoch nicht verkehrt.