DE – Das Skript konvertiert Registry-Dateien (sog. *.reg-Files) in XML-Dateien für die Gruppenrichtlinien Managementkonsole. Es bedient alle gängigen Registry-Formate: REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ, REG_BINARY, REG_DWORD, REG_QWORD
EN – The script converts registry files (so called *.reg files) into XML files for the group policy management console. It serves all common registry formats: REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ, REG_BINARY, REG_DWORD, REG_QWORD
Voraussetzungen / Prerequisites
- Powershell Version 3
Parameter
- FilePath (mandatory, erforderlich – string) – EN: Path to reg-file. DE: Hier geben Sie den Pfad zur Reg-Datei an
- ActionType (optional, string) – EN: Choose the action; DE: Wähle die Tätigkeit; -> Create, Delete, Update, Replace; Default = Update
- BypassErrors (optional, switch) – EN: Continue processing on clients even if an error occur; DE: Die Verarbeitung wird im Fehlerfall auf einem Client fortgesetzt.
Beispiele / Examples
Convert-RegToGppXml.ps1 "C:\Sub Folder\MyTestRegFile.reg" Convert-RegToGppXml.ps1 -FilePath "C:\Sub Folder\MyTestRegFile.reg" Convert-RegToGppXml.ps1 -FilePath "C:\Sub Folder\MyTestRegFile.reg" -ActionType Create Convert-RegToGppXml.ps1 -FilePath "C:\Sub Folder\MyTestRegFile.reg" -ActionType Replace -BypassErrors

Anleitungen / Manuals
FAQ-O-Matic.de | Umwandeln von Registry-Dateien zu XML-Dateien für die GPP
https://www.faq-o-matic.net/2015/04/15/umwandeln-von-registry-dateien-zu-xml-dateien-fr-die-gpp/
Changelog 1.4.1
- [BUG sovled] Values are not written out
- [BUG sovled] REG_BINARY processed as REG_DWORD, may a PS-Bug. Part ist rewritten.
- [BUG sovled] In REG_BINARY „,“ was not removed correctly
- [BUG sovled] In very rare szenarios REG_SZ double quotes are removed
- [ADD] Script can find Control-Chars in String and skip the illegal character
- [ADD] Add UID Attribut
- [ADD] Add Changed Attribut
- [ADD] Add Setting BypassErrors. Continue processing in the event of an error in GPP
Downloads
#requires -Version 3.0 <# Author: Jan Weis Homepage: www.it-explorations.de Mail: jan.weis@it-explorations.de # > # > Wandelt Reg-Dateien in XML-Dateien für die GroupPolicyPreferences um. # > Converts Reg-Files to XML-Files for GroupPolicyPreferences # > [v1.4.1] - 03.2023 + [BUG sovled] Values are not written out + [BUG sovled] REG_BINARY processed as REG_DWORD, may a PS-Bug. Part ist rewritten. + [BUG sovled] In REG_BINARY "," was not removed correctly + [BUG sovled] In very rare szenarios REG_SZ double quotes are removed + [ADD] Script can find Control-Chars in String and skip the illegal character + [ADD] Add UID Attribut + [ADD] Add Changed Attribut + [ADD] Add Setting BypassErrors. Continue processing in the event of an error in GPP [v1.4] - 06.2022 + [BUG] Escape-Zeichen wurden nicht immer entfernt + [ADD] Verarbeitung von weiteren hex-Werten hinzugefügt + [CHANGE] Codeoptimierungen + [CHANGE] Performanceverbesserungen bei großen Dateien #> Param ( [Parameter(Mandatory, Position = 0)] [string[]] $FilePath, [Parameter(Position = 1)] [ValidateSet('Create','Update','Delete','Replace')] [string] $ActionType = 'Update', [switch] $BypassErrors ) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Load Functions # # begin { $currentSkriptVersion = '1.4.1' Write-Output "`n# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #" Write-Output '|' Write-Output "|> Registry-To-XML Converter $currentSkriptVersion von Jan Weis ]" Write-Output '|> Web: www.it-explorations.de; Mail: jan.weis@it-explorations.de ]' Write-Output '|' Write-Output "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #`n" function Convert-HexTostring { param ( [Parameter(Mandatory)] [string] $HexDataString ) [byte[]]$byteArray = ForEach ($hexItem in $HexDataString.Split(',')) { [byte]::Parse($hexItem ,[Globalization.NumberStyles]::HexNumber) } $result = [Text.Encoding]::Unicode.GetString($byteArray) return $result } function New-XmlWriter { param ( [Parameter(Mandatory)] [string] $FileOutPath ) # XML-WRITER-SETTINGS $objXmlWriterSettings = [Xml.XmlWriterSettings]::new() $objXmlWriterSettings.Indent = $True $objXmlWriterSettings.Encoding = [Text.Encoding]::Unicode $objXmlWriterSettings.Async = $true $objXmlWriterSettings.OmitXmlDeclaration = $True $objXmlWriterSettings.WriteEndDocumentOnClose = $True # XML-WRITER [Xml.XmlWriter]$objXmlWriter = [Xml.XmlWriter]::Create($FileOutPath,$objXmlWriterSettings) $objXmlWriter.WriteStartDocument() $objXmlWriter.WriteStartElement('RegistrySettings') $objXmlWriter.WriteAttributestring('clsid','{A3CCFC41-DFDB-43a5-8D26-0FE8B954DA51}') Return $objXmlWriter } function New-XmlEntry { param ( [Parameter(Mandatory)] [Xml.XmlWriter] $XmlWriterObject, [string] $Eintrag = '', [string] $Wert = '', [Parameter(Mandatory)] [ValidateSet('REG_SZ','REG_DWORD','REG_EXPAND_SZ','REG_MULTI_SZ','REG_QWORD','REG_BINARY','REG_NONE')] [string] $RegistryType, [Parameter(ValueFromPipeline)] [ValidateSet('Create','Update','Delete','Replace')] [string] $ActionType = 'Update', [Parameter(Mandatory)] [string] $Hive, [Parameter(Mandatory)] [string] $Key, [bool] $IsDefaultEntry = $false, [string[]] $ExtendedValue = $null ) [Int]$isDefault = 0 # INIT [string]$uid = "{$((New-Guid).ToString())}" [string]$changed = [datetime]::Now.ToString('yyyy-MM-dd HH:MM:ss') If($RegistryType -like 'REG_NONE') { Write-Warning -Message '[*] REG_NONE wird nicht unterstützt!' Return $True } If($IsDefaultEntry) { [Int]$isDefault = 1 } # Setup Picture if ($RegistryType -eq 'REG_SZ' -or $RegistryType -eq 'REG_EXPAND_SZ' -or $RegistryType -eq 'REG_MULTI_SZ') { Switch ($ActionType) { 'Create' { $Type = 'C' $intImage = 5 } 'Delete' { $Type = 'D' $intImage = 8 } 'Replace' { $Type = 'R' $intImage = 6 } 'Update' { $Type = 'U' $intImage = 7 } } } Else { Switch ($ActionType) { 'Create' { $Type = 'C' $intImage = 10 } 'Delete' { $Type = 'D' $intImage = 13 } 'Replace' { $Type = 'R' $intImage = 11 } 'Update' { $Type = 'U' $intImage = 17 } } } try { # DEFAULT Registry $XmlWriterObject.WriteStartElement('Registry') # Open Registry $XmlWriterObject.WriteAttributestring('clsid','{9CD4B2F4-923D-47f5-A062-E897DD1DAD50}') $XmlWriterObject.WriteAttributestring('uid',$uid) $XmlWriterObject.WriteAttributestring('changed',$changed) if($BypassErrors) { $XmlWriterObject.WriteAttributestring('bypassErrors','1') } # SETTINGS Registry If($IsDefaultEntry) { # Standard-Eintrag $XmlWriterObject.WriteAttributestring('name','Hive') $XmlWriterObject.WriteAttributestring('status','(Default)') } else { # Daten-Eintrag $XmlWriterObject.WriteAttributestring('name',$Eintrag) $XmlWriterObject.WriteAttributestring('status',$Eintrag) } $XmlWriterObject.WriteAttributestring('image',$intImage) $XmlWriterObject.WriteAttributestring('descr','Imported with RegToGppXML-Converter (it-explorations.de)') # SETTINGS Properties $XmlWriterObject.WriteStartElement('Properties') # Open Properties $XmlWriterObject.WriteAttributestring('action',$Type) $XmlWriterObject.WriteAttributestring('hive',$Hive) $XmlWriterObject.WriteAttributestring('key',$Key) $XmlWriterObject.Writeattributestring('name',$Eintrag) $XmlWriterObject.Writeattributestring('type',$RegistryType) $XmlWriterObject.WriteAttributestring('displayDecimal',0) $XmlWriterObject.WriteAttributestring('value',$Wert) $XmlWriterObject.WriteAttributestring('default',$isDefault) # SPEZIAL FÜR REG_MULTI_SZ if ($null -ne $ExtendedValue) { $XmlWriterObject.WriteStartElement('Values') # Open Values ForEach ($ExtendedItem in $ExtendedValue) { $XmlWriterObject.WriteStartElement('Value') # Open Value $XmlWriterObject.Writestring($ExtendedItem) $null = Close-XmlEntry -XmlWriterObject $XmlWriterObject # Close Value } $null = Close-XmlEntry -XmlWriterObject $XmlWriterObject # Close Values } # CLOSE WRITER $null = Close-XmlEntry -XmlWriterObject $XmlWriterObject # Close Properties $null = Close-XmlEntry -XmlWriterObject $XmlWriterObject # Close Registry Write-Verbose -Message '[New-XmlEntry] Eintrag erfolgreich geschrieben!' } catch { Write-Warning -Message ('[New-XmlEntry] {0}' -f $_) Write-Warning -Message ("[New-XmlEntry DEBUG] Typ:'{0}'; Hive:'{1}'; Key:'{2}'; Eintrag:'{3}'; Wert:'{4}'" -f $RegistryType, $Hive, $Key, $Eintrag, $Wert) } } function Close-XmlEntry { param ( [Parameter(Mandatory)] [Xml.XmlWriter] $XmlWriterObject ) # Schließe Eintrag $XmlWriterObject.WriteEndElement() $XmlWriterObject.Flush() Write-Verbose -Message '[Close-XmlEntry] XML-Eintrag wurde erfolgreich geschlossen!' } function New-XmlCollection { param ( [Parameter(Mandatory)] [string] $CollectionName, [Parameter(Mandatory)] [Xml.XmlWriter] $XmlWriterObject ) $XmlWriterObject.WriteStartElement('Collection') $XmlWriterObject.WriteAttributestring('clsid','{53B533F5-224C-47e3-B01B-CA3B3F3FF4BF}') $XmlWriterObject.WriteAttributestring('name',$CollectionName) Write-Verbose -Message '[New-XmlCollection] Neue Collection wurde erfolgreich angelegt!' } } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Script / Skript # # process { Write-Progress -Activity 'Registry To XML Converter' -Status 'REG-Datei wird eingelesen' # Process each File ForEach ($FileItemPath in $FilePath) { [string]$Wert = '' # INIT [string]$currentHive = '' # INIT [string]$currentKey = '' # INIT [string[]]$currentKeyArray = '' # INIT [string[]]$lastKeyArray = '' # INIT [long]$currentLineNumber = 0 # INIT [string]$lastKey = '' [string]$lastHive = '' [string]$lastKeyWithWrittenData = '' # Valid Path $FileItemPath = $FileItemPath.replace('"','').trim() If ((Test-Path -Path $FileItemPath) -eq $false) { Write-Warning -Message ('File not exist. FilePath:{0}' -f $FileItemPath) Continue } # Valid Filetype If ((Get-Item -Path $FileItemPath).Extension -notlike '.reg') { Write-Error -Message 'Wrong Filetype! Only Registry Filetype acceppted.' Continue } # Read File [IO.StreamReader]$streamReader = $null try { [IO.StreamReader]$streamReader = [IO.File]::OpenText($FileItemPath) } catch { Write-Warning -Message "[*] Datei kann nicht gelesen werden! Path:$FileItemPath" continue } # New XmlWriter [string]$xmlOutputFilePath = ('{0}.xml' -f $FileItemPath) [Xml.XmlWriter]$xmlWriter = $null try { [Xml.XmlWriter]$xmlWriter = New-XmlWriter -FileOutPath $xmlOutputFilePath } catch { Write-Warning -Message "[*] Fehler: XmlWriter konnte nicht erstellt werden! Skriptende! Path:$xmlOutputFilePath" $streamReader.Close() exit } # Process each Line while ($streamReader.EndOfStream.Equals($false) -and (($xmlWriter.WriteState -ne 5) -and ($xmlWriter.WriteState -ne 6))) { # Progress if(($currentLineNumber / 200) % 2 -eq 0) { Write-Progress -Activity 'Registry To XML Converter' -CurrentOperation 'Verarbeite REG-Datei' -Status $currentLineNumber Write-Output "[*] Processed Reglines: $currentLineNumber" } [string]$itemValue = '' # INIT [string]$itemName = '' # INIT [string]$itemValueType = '' # INIT [bool]$isDefaultItem = $false # INIT [string[]]$itemHexValueArray = $null [bool]$skipCurrentItem = $false [int]$startValueDataIndex = 0 # Lese neue Zeile ein [string]$lineContent = $streamReader.ReadLine() $currentLineNumber++ # No Input? if($null -eq $lineContent -or $lineContent -like '') { continue } # # # if($lineContent.StartsWith('[')) # Hive Key Procesing { # Hive Key Procesing # DEFINIERE AKTUELLEN HEADER [string]$tempKey = $lineContent.Replace('[','').Replace(']','') [string]$currentHive = $tempKey.Substring(0,$tempKey.IndexOf('\')) [string]$currentKey = $tempKey.Substring($tempKey.IndexOf('\') +1) [string[]]$currentKeyArray = $tempKey.Split('\') # VERGLEICHE ALTEN UND NEUEN HEADER $keyCompareResult = Compare-Object -ReferenceObject $lastKeyArray -DifferenceObject $currentKeyArray -PassThru | Where-Object { $_ -ne '' } # Close old Header and open new Header $closingKeys = $keyCompareResult | Where-Object { $_.SideIndicator -eq '<=' } # Verify if the last key was written if($null -ne $closingKeys) { if($lastKey -ne $lastKeyWithWrittenData) { # Write empty Key New-XmlEntry -XmlWriterObject $xmlWriter -RegistryType REG_SZ -Hive $lastHive -Key $lastKey -IsDefaultEntry $false } } $closingKeys| ForEach-Object { Close-XmlEntry -XmlWriterObject $xmlWriter } $keyCompareResult | Where-Object { $_.SideIndicator -eq '=>' } | ForEach-Object { New-XmlCollection -CollectionName $_ -XmlWriterObject $xmlWriter } } elseif($lineContent.StartsWith('"') -or $lineContent.StartsWith('@')) # Data Procesing { # Data Procesing # # GET ITEM NAME # If($lineContent.StartsWith('@')) { $isDefaultItem = $true [int]$endOfNameIndex = 0 } else { [int]$endOfNameIndex = $lineContent.IndexOf('"=') [string]$itemName = $lineContent.Substring(1,$endOfNameIndex -1) } # # GET ITEM VALUE RAW # [int]$beginOfValueIndex = $endOfNameIndex + 2 $itemValueRaw = $lineContent.Substring($beginOfValueIndex) # # GET ITEM VALUE TYPE # ## Define RegType if($itemValueRaw.StartsWith('"')) { # string $itemValueType = 'string' $startValueDataIndex = 0 } elseif($itemValueRaw.StartsWith('d')) { # dword $itemValueType = 'dword' $startValueDataIndex = 6 } elseif($itemValueRaw.StartsWith('h')) { # hex [int]$endTypePosition = $itemValueRaw.IndexOf(':') [string]$itemValueType = $itemValueRaw.Substring(0,$endTypePosition) $startValueDataIndex = $endTypePosition +1 } else { Write-Warning -Message "[!] Unknown Item Datatype!" continue } # # GET ITEM VALUE DATA # [string]$itemValueDataRaw = $itemValueRaw.Substring($startValueDataIndex) if($itemValueDataRaw.EndsWith('\') -eq $false) { # One line Value if($itemValueDataRaw -match "[\x00-\x17]") { Write-Warning -Message "[!] Control Char found! This cannot be proceeded! Skip Line $currentLineNumber" $skipCurrentItem = $true } } else { # More line Values $regLineData = $itemValueDataRaw do { $newLine = $streamReader.ReadLine() $currentLineNumber++ $lineDataTemp = $newLine.Substring(2) $regLineData = $regLineData + $lineDataTemp } while ($regLineData.EndsWith('\') -eq $True) # Cleanup Data $itemValueDataRaw = $regLineData.Replace('\','') } # # PROCESS ITEM VALUE # # REG_SZ if($itemValueType -like 'string') { [string]$RegItemType = 'REG_SZ' [string]$itemValueTemp = [regex]::Unescape($itemValueDataRaw) # Remove Escape if($itemValueTemp.Length -gt 2) { [string]$itemValueTemp = $itemValueTemp.Substring(1,$itemValueTemp.Length -2) } else { if($itemValueTemp.Length -le 2) { [string]$itemValueTemp = '' } } [string]$itemValue = $itemValueTemp } # REG_BINARY elseif($itemValueType -like 'hex' -or $itemValueType -like 'hex(3)') { [string]$RegItemType = 'REG_BINARY' [string]$itemValue = $itemValueDataRaw.Replace(',','').Trim() } # REG_DWORD elseif($itemValueType -like 'dword' -or $itemValueType -like 'hex(4)') { [string]$RegItemType = 'REG_DWORD' [string]$itemValue = $itemValueDataRaw } # REG_EXPAND_SZ elseif($itemValueType -like 'hex(2)') { [string]$RegItemType = 'REG_EXPAND_SZ' [string[]]$itemHexValueArray = $null # Remove unesessary Escapes if($itemValueDataRaw.EndsWith(',00,00')) { # Contains Data $itemValueDataRaw = $itemValueDataRaw.Replace(',00,00','') [string]$itemValue = Convert-HexTostring -HexDataString $itemValueDataRaw } elseif($itemValueDataRaw.EndsWith('00,00')) { # Empty Item [string]$itemValue = '' } } # REG_MULTI_SZ elseif($itemValueType -like 'hex(7)') { [string]$RegItemType = 'REG_MULTI_SZ' # Remove unesessary Escapes if($itemValueDataRaw.EndsWith(',00,00,00,00')) { # Contains Data $itemValueDataRaw = $itemValueDataRaw.Replace(',00,00,00,00','') [string[]]$itemHexValueArray = (Convert-HexTostring -HexDataString $itemValueDataRaw).Split("$([Char]00)") [string]$itemValue = $itemHexValueArray -join ' ' } elseif($itemValueDataRaw.EndsWith('00,00')) { # Empty Item $itemValueDataRaw = $itemValueDataRaw.Replace('00,00','') [string[]]$itemHexValueArray = $null [string]$itemValue = '' } } # REG_QWORD elseif($itemValueType -like 'hex(b)') { [string]$RegItemType = 'REG_QWORD' [string]$valueTemp = '' # Invertiere die Daten foreach($Item in $itemValueDataRaw.Split(',')) { $valueTemp = "$Item$valueTemp" } [string]$itemValue = $valueTemp } # REG_NONE, Type NOT Supported! elseif($itemValueType -like 'hex(0)') { [string]$RegItemType = 'REG_NONE' Write-Warning -Message '[*] REG_NONE by GPP is not supported! Item skipped!' $skipCurrentItem = $True } # REG_DWORD_BIG_ENDIAN, Type NOT Supported! elseif($itemValueType -like 'hex(5)') { [string]$RegItemType = 'REG_DWORD_BIG_ENDIAN' Write-Warning -Message '[*] REG_DWORD_BIG_ENDIAN by GPP is not supported! Item skipped!' $skipCurrentItem = $True } # REG_LINK, Type NOT Supported! elseif($itemValueType -like 'hex(6)') { # USE RAW DATA [string]$RegItemType = 'REG_LINK' Write-Warning -Message '[*] REG_LINK by GPP is not supported! Item skipped!' $skipCurrentItem = $True } else { Write-Warning -Message ('[*] Unbekannter Registry-Type! RegTyp:{0};RegZeile:{1}' -f $itemValueType, $currentLineNumber) } #Skip unsupported RegType if ($skipCurrentItem -eq $true) { continue } $null = New-XmlEntry -Eintrag $itemName -RegistryType $RegItemType -Wert $itemValue -Hive $currentHive -Key $currentKey -XmlWriterObject $xmlWriter -ActionType $ActionType -ExtendedValue $itemHexValueArray -IsDefaultEntry $isDefaultItem [string]$lastKeyWithWrittenData = $currentKey } [string[]]$lastKeyArray = $currentKeyArray [string]$lastKey = $currentKey [string]$lastHive = $currentHive } # Finishing... Write-Output "[*] Processed Reglines: $currentLineNumber" Write-Progress -Activity 'Registry To XML Converter' -CurrentOperation 'XML-Datei wird geschrieben...' -Completed Write-Output -InputObject ("`n[*] Writing XML-File {0} ..." -f $xmlOutputFilePath) try { # Letzten Eintrag schließen $null = Close-XmlEntry -XmlWriterObject $xmlWriter # ABSCHLUSS $xmlWriter.Close() $streamReader.Close() Write-Output -InputObject '[*] File successfully written!' } catch { Write-Warning -Message ('[*] {0}' -f $_) # Letzten Eintrag schließen $null = Close-XmlEntry -XmlWriterObject $xmlWriter $streamReader.Close() } Write-Progress -Activity 'Registry To XML Converter' -Completed } } end { Write-Output -InputObject @' __________ < Bye Bye! > ---------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || '@ }
Pingback: Registry nach XML Converter für GPP - IT Explorations