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