Importing Reg Files Into Group Policy Preferences

Surprisingly there doesn’t seem to be any obvious way to import “reg” files into Group Policy Preferences. And using the Registry Import Wizard can be tedious ticking many many tick boxes.

Looking around existing tools I could find one commercial tool but nothing freely available, so put together a PowerShell script to convert a .REG file to a .XML file that can be dragged and dropped into a Group Policy Preference.

This script supports the following registry types:

  • REG_DWORD
  • REG_QWORD
  • REG_EXPAND_SZ
  • REG_MULTI_SZ
  • REG_BINARY
  • REG_SZ

Note: Your reg file should contain data from one hive only (i.e. HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE) as the Group Policy preference XML doesn’t allow two hive types.

Usage:

Convert-Reg2Xml -regPath input.reg -xmlPath output.xml

Then drag and drop XML file into the registry section of Group Policy preference editor.

(Tested on Windows Server 2012 R2 only, but expect it to work on other servers/clients)

Note: There is pretty much no error checking currently in script. It is assumed reg file is exported from reg edit. If you manually created reg file with slight differences from reg edit export this tool may not process reg file correctly.

Script can be downloaded here: https://onedrive.live.com/redir?resid=93A8E9D387076121!1388&authkey=!AJFuJBPvhP5vAyk&ithint=file%2c.zip

function Convert-RegEscapeCodes { Param( [Parameter(Position=1)][string]$regstring) return $regstring.Replace("\\","\").Replace('\"','"') } function Convert-Reg2Xml { Param( [Parameter(Mandatory=$True)][string]$regPath, [Parameter(Mandatory=$True)][string]$xmlPath ) $clsidCollection = "{53B533F5-224C-47e3-B01B-CA3B3F3FF4BF}" $clsidRegistry = "{9CD4B2F4-923D-47f5-A062-E897DD1DAD50}" $settings = New-Object System.Xml.XmlWriterSettings $settings.Indent=$True $settings.Encoding = [System.Text.Encoding]::UTF8 $xml = [System.Xml.XmlWriter]::Create($xmlPath,$settings) $descr = "Imported Reg File" $action = "U" $unicoder = New-Object System.Text.UnicodeEncoding $lastHive=""; $lastKey=""; $sr=New-Object System.IO.StreamReader($regPath) $lastHive="" $lastKey="" $collectionCount=0 while (!$sr.EndOfStream) { $line = $sr.ReadLine() if ($line.StartsWith("[")) { $currentHive=$line.Substring(1,$line.IndexOf("\")-1) $currentKey=$line.Substring($line.IndexOf("\")+1,$line.Length-$line.IndexOf("\")-2) if ($lastHive -eq "") { $xml.WriteStartElement("Collection") $xml.WriteAttributeString("clsid",$clsidCollection) $xml.WriteAttributeString("name",$currentHive) $collectionCount++ ForEach ($key in $currentKey.Split('\')) { $xml.WriteStartElement("Collection") $xml.WriteAttributeString("clsid",$clsidCollection) $xml.WriteAttributeString("name",$key) $collectionCount++ } } else { # hives don't match - settings.xml doesn't support this! if ($currentHive -ne $lastHive) { # invalid - settings.xml only supports one HIVE type per file Throw "Reg file format is not supported by settings .XML. Please use only $currentHive or $lastHive per XML file" return } else { # going up a key if ($currentKey.StartsWith($lastKey + "\")) { $newKey=$currentKey.Substring($lastKey.Length+1) ForEach ($key in $newKey.Split('\')) { $xml.WriteStartElement("Collection") $xml.WriteAttributeString("clsid",$clsidCollection) $xml.WriteAttributeString("name",$key) $collectionCount++ } } else { # funky logic to handle change in key path # maybe this logic even works :) $currentKeySplit=$currentKey.Split('\') $lastKeySplit=$lastKey.Split('\') $match=$true $i=-1 while ($match) { $i++ if ($i -ge $currentKeySplit.Length -or $i -ge $lastKeySplit.Length) { $match=$false } else { if ($currentKeySplit[$i] -ne $lastKeySplit[$i]) { $match=$false } } } for ($x=$lastKeySplit.Length;$x -gt $i;$x--) { $xml.WriteEndElement() $collectionCount-- } for ($x=$i;$x -lt $currentKeySplit.Length;$x++) { $xml.WriteStartElement("Collection") $xml.WriteAttributeString("clsid",$clsidCollection) $xml.WriteAttributeString("name",$currentKeySplit[$x]) $collectionCount++ } } } } $lastHive=$currentHive $lastKey=$currentKey } else { if ($line.Contains("=")) { $regType=[Microsoft.Win32.RegistryValueKind]::Unknown # detect registry type if ($line.StartsWith("@=") -or $line.Contains('"="')) { $regType=[Microsoft.Win32.RegistryValueKind]::String } if ($line.Contains("=hex:")) { $regType=[Microsoft.Win32.RegistryValueKind]::Binary } if ($line.Contains("=dword:")) { $regType=[Microsoft.Win32.RegistryValueKind]::DWord } if ($line.Contains("=hex(7):")) { $regType=[Microsoft.Win32.RegistryValueKind]::MultiString } if ($line.Contains("=hex(2):")) { $regType=[Microsoft.Win32.RegistryValueKind]::ExpandString } if ($line.Contains("=hex(b):")) { $regType=[Microsoft.Win32.RegistryValueKind]::QWord } switch ($regType) { # *** PROCESS REG_SZ ([Microsoft.Win32.RegistryValueKind]::String) { $default="0" if ($line.StartsWith("@=")) { $valueName="" $value=$line.Substring(3,$line.Length-4) "Name = '$valueName' Value = '$value'" $default="1" } else { $i = $line.IndexOf('"="') $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1) $value=Convert-RegEscapeCodes $line.Substring($i+3,$line.Length-$i-4) "Name = '$valueName' Value = '$value'" } $xml.WriteStartElement("Registry") $xml.WriteAttributeString("clsid",$clsidRegistry) $xml.WriteAttributeString("name",$valueName) $xml.WriteAttributeString("descr",$descr) $xml.WriteAttributeString("image","7") $xml.WriteStartElement("Properties") $xml.WriteAttributeString("action",$action) $xml.WriteAttributeString("hive",$currentHive) $xml.WriteAttributeString("key",$currentKey) $xml.WriteattributeString("name",$valueName) $xml.WriteattributeString("default",$default) $xml.WriteattributeString("type","REG_SZ") $xml.WriteattributeString("displayDecimal","0") $xml.WriteAttributeString("value",$value) $xml.WriteEndElement() $xml.WriteEndElement() } # *** PROCESS REG_BINARY ([Microsoft.Win32.RegistryValueKind]::Binary) { # read binary key to end while ($line.EndsWith("\")) { $line=$line.Substring(0,$line.Length-1)+$sr.ReadLine().Trim() } $i = $line.IndexOf('"=hex:') $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1) $value=$line.Substring($i+6).Replace(",","") "Name = '$valueName' Value = '$value'" # build XML $xml.WriteStartElement("Registry") $xml.WriteAttributeString("clsid",$clsidRegistry) $xml.WriteAttributeString("name",$valueName) $xml.WriteAttributeString("descr",$descr) $xml.WriteAttributeString("image","17") $xml.WriteStartElement("Properties") $xml.WriteAttributeString("action",$action) $xml.WriteAttributeString("hive",$currentHive) $xml.WriteAttributeString("key",$currentKey) $xml.WriteattributeString("name",$valueName) $xml.WriteattributeString("default","0") $xml.WriteattributeString("type","REG_BINARY") $xml.WriteattributeString("displayDecimal","0") $xml.WriteAttributeString("value",$value) $xml.WriteEndElement() $xml.WriteEndElement() } # *** PROCESS REG_DWORD ([Microsoft.Win32.RegistryValueKind]::DWord) { $i = $line.IndexOf('"=dword:') $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1) $value=$line.Substring($i+8).ToUpper() "Name = '$valueName' Value = '$value'" # build XML $xml.WriteStartElement("Registry") $xml.WriteAttributeString("clsid",$clsidRegistry) $xml.WriteAttributeString("name",$valueName) $xml.WriteAttributeString("descr",$descr) $xml.WriteAttributeString("image","17") $xml.WriteStartElement("Properties") $xml.WriteAttributeString("action",$action) $xml.WriteAttributeString("hive",$currentHive) $xml.WriteAttributeString("key",$currentKey) $xml.WriteattributeString("name",$valueName) $xml.WriteattributeString("default","0") $xml.WriteattributeString("type","REG_DWORD") $xml.WriteattributeString("displayDecimal","0") $xml.WriteAttributeString("value",$value) $xml.WriteEndElement() $xml.WriteEndElement() } # *** PROCESS REG_QWORD ([Microsoft.Win32.RegistryValueKind]::QWord) { $i = $line.IndexOf('"=hex(b):') $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1) $tempValue=$line.Substring($i+9).Replace(",","").ToUpper() $value="" # unreverse QWORD for settings.xml format for ($i = $tempValue.Length -2;$i -gt 0;$i-=2) { $value+=$tempValue.Substring($i,2) } "Name = '$valueName' Value = '$value'" # build XML $xml.WriteStartElement("Registry") $xml.WriteAttributeString("clsid",$clsidRegistry) $xml.WriteAttributeString("name",$valueName) $xml.WriteAttributeString("descr",$descr) $xml.WriteAttributeString("image","17") $xml.WriteStartElement("Properties") $xml.WriteAttributeString("action",$action) $xml.WriteAttributeString("hive",$currentHive) $xml.WriteAttributeString("key",$currentKey) $xml.WriteattributeString("name",$valueName) $xml.WriteattributeString("default","0") $xml.WriteattributeString("type","REG_QWORD") $xml.WriteattributeString("displayDecimal","0") $xml.WriteAttributeString("value",$value) $xml.WriteEndElement() $xml.WriteEndElement() } # *** PROESS REG_MULTI_MZ ([Microsoft.Win32.RegistryValueKind]::MultiString) { # read binary key to end while ($line.EndsWith("\")) { $line=$line.Substring(0,$line.Length-1)+$sr.ReadLine().Trim() } # read hex codes $i = $line.IndexOf('"=hex(7):') $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1) $value=$line.Substring($i+9).Replace(",","") # convert hex codes to binary array $byteLength=$value.Length/2 $byte = New-Object Byte[] $byteLength $x=0 for ($i=0;$i -lt $value.Length;$i+=2) { $byte[$x]="0x" + $value.Substring($i,2) $x++ } # convert binary array to unicode string $value=$unicoder.GetString($byte) # retrieve multi values $values=$value.Replace("`0`0","").Split("`0") "Name = '$valueName'" # build XML $xml.WriteStartElement("Registry") $xml.WriteAttributeString("clsid",$clsidRegistry) $xml.WriteAttributeString("name",$valueName) $xml.WriteAttributeString("descr",$descr) $xml.WriteAttributeString("image","7") $xml.WriteStartElement("Properties") $xml.WriteAttributeString("action",$action) $xml.WriteAttributeString("hive",$currentHive) $xml.WriteAttributeString("key",$currentKey) $xml.WriteattributeString("name",$valueName) $xml.WriteattributeString("default","0") $xml.WriteattributeString("type","REG_MULTI_SZ") $xml.WriteattributeString("displayDecimal","0") $xml.WriteAttributeString("value",$value.Replace("`0"," ")) $x=1 $xml.WriteStartElement("Values") ForEach ($value in $values) { $xml.WriteStartElement("Value") $xml.WriteString($value) "Value $x = '$value'" $xml.WriteEndElement() } $xml.WriteEndElement() $xml.WriteEndElement() $xml.WriteEndElement() } ([Microsoft.Win32.RegistryValueKind]::ExpandString) { # read binary key to end while ($line.EndsWith("\")) { $line=$line.Substring(0,$line.Length-1)+$sr.ReadLine().Trim() } # read hex codes $i = $line.IndexOf('"=hex(2):') $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1) $value=$line.Substring($i+9).Replace(",","") # convert hex codes to binary array $byteLength=$value.Length/2 $byte = New-Object Byte[] $byteLength $x=0 for ($i=0;$i -lt $value.Length;$i+=2) { $byte[$x]="0x" + $value.Substring($i,2) $x++ } # convert binary array to unicode string $value=$unicoder.GetString($byte).Replace("`0","") "Name = '$valueName' Value = '$value'" $xml.WriteStartElement("Registry") $xml.WriteAttributeString("clsid",$clsidRegistry) $xml.WriteAttributeString("name",$valueName) $xml.WriteAttributeString("descr",$descr) $xml.WriteAttributeString("image","7") $xml.WriteStartElement("Properties") $xml.WriteAttributeString("action",$action) $xml.WriteAttributeString("hive",$currentHive) $xml.WriteAttributeString("key",$currentKey) $xml.WriteattributeString("name",$valueName) $xml.WriteattributeString("default",$default) $xml.WriteattributeString("type","REG_EXPAND_SZ") $xml.WriteattributeString("displayDecimal","0") $xml.WriteAttributeString("value",$value) $xml.WriteEndElement() $xml.WriteEndElement() } } } } } $sr.Close() while ($collectionCount -gt 0) { $xml.WriteEndElement() $collectionCount-- } $xml.Close() } Convert-Reg2Xml -regPath "C:\support\ReceiverCSTRegUpx64.reg" -xmlPath C:\support\Citrix.xmlfunction Convert-RegEscapeCodes { Param( [Parameter(Position=1)][string]$regstring) return $regstring.Replace("\\","\").Replace('\"','"') } function Convert-Reg2Xml { Param( [Parameter(Mandatory=$True)][string]$regPath, [Parameter(Mandatory=$True)][string]$xmlPath ) $clsidCollection = "{53B533F5-224C-47e3-B01B-CA3B3F3FF4BF}" $clsidRegistry = "{9CD4B2F4-923D-47f5-A062-E897DD1DAD50}" $settings = New-Object System.Xml.XmlWriterSettings $settings.Indent=$True $settings.Encoding = [System.Text.Encoding]::UTF8 $xml = [System.Xml.XmlWriter]::Create($xmlPath,$settings) $descr = "Imported Reg File" $action = "U" $unicoder = New-Object System.Text.UnicodeEncoding $lastHive=""; $lastKey=""; $sr=New-Object System.IO.StreamReader($regPath) $lastHive="" $lastKey="" $collectionCount=0 while (!$sr.EndOfStream) { $line = $sr.ReadLine() if ($line.StartsWith("[")) { $currentHive=$line.Substring(1,$line.IndexOf("\")-1) $currentKey=$line.Substring($line.IndexOf("\")+1,$line.Length-$line.IndexOf("\")-2) if ($lastHive -eq "") { $xml.WriteStartElement("Collection") $xml.WriteAttributeString("clsid",$clsidCollection) $xml.WriteAttributeString("name",$currentHive) $collectionCount++ ForEach ($key in $currentKey.Split('\')) { $xml.WriteStartElement("Collection") $xml.WriteAttributeString("clsid",$clsidCollection) $xml.WriteAttributeString("name",$key) $collectionCount++ } } else { # hives don't match - settings.xml doesn't support this! if ($currentHive -ne $lastHive) { # invalid - settings.xml only supports one HIVE type per file Throw "Reg file format is not supported by settings .XML. Please use only $currentHive or $lastHive per XML file" return } else { # going up a key if ($currentKey.StartsWith($lastKey + "\")) { $newKey=$currentKey.Substring($lastKey.Length+1) ForEach ($key in $newKey.Split('\')) { $xml.WriteStartElement("Collection") $xml.WriteAttributeString("clsid",$clsidCollection) $xml.WriteAttributeString("name",$key) $collectionCount++ } } else { # funky logic to handle change in key path # maybe this logic even works :) $currentKeySplit=$currentKey.Split('\') $lastKeySplit=$lastKey.Split('\') $match=$true $i=-1 while ($match) { $i++ if ($i -ge $currentKeySplit.Length -or $i -ge $lastKeySplit.Length) { $match=$false } else { if ($currentKeySplit[$i] -ne $lastKeySplit[$i]) { $match=$false } } } for ($x=$lastKeySplit.Length;$x -gt $i;$x--) { $xml.WriteEndElement() $collectionCount-- } for ($x=$i;$x -lt $currentKeySplit.Length;$x++) { $xml.WriteStartElement("Collection") $xml.WriteAttributeString("clsid",$clsidCollection) $xml.WriteAttributeString("name",$currentKeySplit[$x]) $collectionCount++ } } } } $lastHive=$currentHive $lastKey=$currentKey } else { if ($line.Contains("=")) { $regType=[Microsoft.Win32.RegistryValueKind]::Unknown # detect registry type if ($line.StartsWith("@=") -or $line.Contains('"="')) { $regType=[Microsoft.Win32.RegistryValueKind]::String } if ($line.Contains("=hex:")) { $regType=[Microsoft.Win32.RegistryValueKind]::Binary } if ($line.Contains("=dword:")) { $regType=[Microsoft.Win32.RegistryValueKind]::DWord } if ($line.Contains("=hex(7):")) { $regType=[Microsoft.Win32.RegistryValueKind]::MultiString } if ($line.Contains("=hex(2):")) { $regType=[Microsoft.Win32.RegistryValueKind]::ExpandString } if ($line.Contains("=hex(b):")) { $regType=[Microsoft.Win32.RegistryValueKind]::QWord } switch ($regType) { # *** PROCESS REG_SZ ([Microsoft.Win32.RegistryValueKind]::String) { $default="0" if ($line.StartsWith("@=")) { $valueName="" $value=$line.Substring(3,$line.Length-4) "Name = '$valueName' Value = '$value'" $default="1" } else { $i = $line.IndexOf('"="') $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1) $value=Convert-RegEscapeCodes $line.Substring($i+3,$line.Length-$i-4) "Name = '$valueName' Value = '$value'" } $xml.WriteStartElement("Registry") $xml.WriteAttributeString("clsid",$clsidRegistry) $xml.WriteAttributeString("name",$valueName) $xml.WriteAttributeString("descr",$descr) $xml.WriteAttributeString("image","7") $xml.WriteStartElement("Properties") $xml.WriteAttributeString("action",$action) $xml.WriteAttributeString("hive",$currentHive) $xml.WriteAttributeString("key",$currentKey) $xml.WriteattributeString("name",$valueName) $xml.WriteattributeString("default",$default) $xml.WriteattributeString("type","REG_SZ") $xml.WriteattributeString("displayDecimal","0") $xml.WriteAttributeString("value",$value) $xml.WriteEndElement() $xml.WriteEndElement() } # *** PROCESS REG_BINARY ([Microsoft.Win32.RegistryValueKind]::Binary) { # read binary key to end while ($line.EndsWith("\")) { $line=$line.Substring(0,$line.Length-1)+$sr.ReadLine().Trim() } $i = $line.IndexOf('"=hex:') $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1) $value=$line.Substring($i+6).Replace(",","") "Name = '$valueName' Value = '$value'" # build XML $xml.WriteStartElement("Registry") $xml.WriteAttributeString("clsid",$clsidRegistry) $xml.WriteAttributeString("name",$valueName) $xml.WriteAttributeString("descr",$descr) $xml.WriteAttributeString("image","17") $xml.WriteStartElement("Properties") $xml.WriteAttributeString("action",$action) $xml.WriteAttributeString("hive",$currentHive) $xml.WriteAttributeString("key",$currentKey) $xml.WriteattributeString("name",$valueName) $xml.WriteattributeString("default","0") $xml.WriteattributeString("type","REG_BINARY") $xml.WriteattributeString("displayDecimal","0") $xml.WriteAttributeString("value",$value) $xml.WriteEndElement() $xml.WriteEndElement() } # *** PROCESS REG_DWORD ([Microsoft.Win32.RegistryValueKind]::DWord) { $i = $line.IndexOf('"=dword:') $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1) $value=$line.Substring($i+8).ToUpper() "Name = '$valueName' Value = '$value'" # build XML $xml.WriteStartElement("Registry") $xml.WriteAttributeString("clsid",$clsidRegistry) $xml.WriteAttributeString("name",$valueName) $xml.WriteAttributeString("descr",$descr) $xml.WriteAttributeString("image","17") $xml.WriteStartElement("Properties") $xml.WriteAttributeString("action",$action) $xml.WriteAttributeString("hive",$currentHive) $xml.WriteAttributeString("key",$currentKey) $xml.WriteattributeString("name",$valueName) $xml.WriteattributeString("default","0") $xml.WriteattributeString("type","REG_DWORD") $xml.WriteattributeString("displayDecimal","0") $xml.WriteAttributeString("value",$value) $xml.WriteEndElement() $xml.WriteEndElement() } # *** PROCESS REG_QWORD ([Microsoft.Win32.RegistryValueKind]::QWord) { $i = $line.IndexOf('"=hex(b):') $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1) $tempValue=$line.Substring($i+9).Replace(",","").ToUpper() $value="" # unreverse QWORD for settings.xml format for ($i = $tempValue.Length -2;$i -gt 0;$i-=2) { $value+=$tempValue.Substring($i,2) } "Name = '$valueName' Value = '$value'" # build XML $xml.WriteStartElement("Registry") $xml.WriteAttributeString("clsid",$clsidRegistry) $xml.WriteAttributeString("name",$valueName) $xml.WriteAttributeString("descr",$descr) $xml.WriteAttributeString("image","17") $xml.WriteStartElement("Properties") $xml.WriteAttributeString("action",$action) $xml.WriteAttributeString("hive",$currentHive) $xml.WriteAttributeString("key",$currentKey) $xml.WriteattributeString("name",$valueName) $xml.WriteattributeString("default","0") $xml.WriteattributeString("type","REG_QWORD") $xml.WriteattributeString("displayDecimal","0") $xml.WriteAttributeString("value",$value) $xml.WriteEndElement() $xml.WriteEndElement() } # *** PROESS REG_MULTI_MZ ([Microsoft.Win32.RegistryValueKind]::MultiString) { # read binary key to end while ($line.EndsWith("\")) { $line=$line.Substring(0,$line.Length-1)+$sr.ReadLine().Trim() } # read hex codes $i = $line.IndexOf('"=hex(7):') $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1) $value=$line.Substring($i+9).Replace(",","") # convert hex codes to binary array $byteLength=$value.Length/2 $byte = New-Object Byte[] $byteLength $x=0 for ($i=0;$i -lt $value.Length;$i+=2) { $byte[$x]="0x" + $value.Substring($i,2) $x++ } # convert binary array to unicode string $value=$unicoder.GetString($byte) # retrieve multi values $values=$value.Replace("`0`0","").Split("`0") "Name = '$valueName'" # build XML $xml.WriteStartElement("Registry") $xml.WriteAttributeString("clsid",$clsidRegistry) $xml.WriteAttributeString("name",$valueName) $xml.WriteAttributeString("descr",$descr) $xml.WriteAttributeString("image","7") $xml.WriteStartElement("Properties") $xml.WriteAttributeString("action",$action) $xml.WriteAttributeString("hive",$currentHive) $xml.WriteAttributeString("key",$currentKey) $xml.WriteattributeString("name",$valueName) $xml.WriteattributeString("default","0") $xml.WriteattributeString("type","REG_MULTI_SZ") $xml.WriteattributeString("displayDecimal","0") $xml.WriteAttributeString("value",$value.Replace("`0"," ")) $x=1 $xml.WriteStartElement("Values") ForEach ($value in $values) { $xml.WriteStartElement("Value") $xml.WriteString($value) "Value $x = '$value'" $xml.WriteEndElement() } $xml.WriteEndElement() $xml.WriteEndElement() $xml.WriteEndElement() } ([Microsoft.Win32.RegistryValueKind]::ExpandString) { # read binary key to end while ($line.EndsWith("\")) { $line=$line.Substring(0,$line.Length-1)+$sr.ReadLine().Trim() } # read hex codes $i = $line.IndexOf('"=hex(2):') $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1) $value=$line.Substring($i+9).Replace(",","") # convert hex codes to binary array $byteLength=$value.Length/2 $byte = New-Object Byte[] $byteLength $x=0 for ($i=0;$i -lt $value.Length;$i+=2) { $byte[$x]="0x" + $value.Substring($i,2) $x++ } # convert binary array to unicode string $value=$unicoder.GetString($byte).Replace("`0","") "Name = '$valueName' Value = '$value'" $xml.WriteStartElement("Registry") $xml.WriteAttributeString("clsid",$clsidRegistry) $xml.WriteAttributeString("name",$valueName) $xml.WriteAttributeString("descr",$descr) $xml.WriteAttributeString("image","7") $xml.WriteStartElement("Properties") $xml.WriteAttributeString("action",$action) $xml.WriteAttributeString("hive",$currentHive) $xml.WriteAttributeString("key",$currentKey) $xml.WriteattributeString("name",$valueName) $xml.WriteattributeString("default",$default) $xml.WriteattributeString("type","REG_EXPAND_SZ") $xml.WriteattributeString("displayDecimal","0") $xml.WriteAttributeString("value",$value) $xml.WriteEndElement() $xml.WriteEndElement() } } } } } $sr.Close() while ($collectionCount -gt 0) { $xml.WriteEndElement() $collectionCount-- } $xml.Close() } Convert-Reg2Xml -regPath "input.reg" -xmlPath output.xml

About chentiangemalc

specializes in end-user computing technologies. disclaimer 1) use at your own risk. test any solution in your environment. if you do not understand the impact/consequences of what you're doing please stop, and ask advice from somebody who does. 2) views are my own at the time of posting and do not necessarily represent my current view or the view of my employer and family members/relatives. 3) over the years Microsoft/Citrix/VMWare have given me a few free shirts, pens, paper notebooks/etc. despite these gifts i will try to remain unbiased.
This entry was posted in Group Policy, PowerShell and tagged , . Bookmark the permalink.

26 Responses to Importing Reg Files Into Group Policy Preferences

  1. Peter B says:

    doesn’t seem to work for me… tried on several machines including 2012r2 and just get:

    You cannot call a method on a null-valued expression.
    At C:\temp\ODBC\RegToXML.ps1:41 char:9
    + if ($line.StartsWith(“[“))
    + ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

  2. Roadie_UK says:

    This is a really helpful script for both learning from and for converting the registry file to XML I have but one question, more for my own sanity.

    Where are you getting the clsid from for the Registry keys and Values?

    regards

  3. Matt says:

    Thank you for taking time to write this script. Having issues running and don’t understand why I get the following error below? Also if line 415 is removed from script the script no longer works? Any help would be appreciated.

    You cannot call a method on a null-valued expression.
    At C:\Temp\RegtoXml\RegToXML.ps1:40 char:5
    + $line = $sr.ReadLine()
    + ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    You cannot call a method on a null-valued expression.
    At C:\Temp\RegtoXml\RegToXML.ps1:41 char:9
    + if ($line.StartsWith(“[“))
    + ~~~~~~~~~~~~~~~~~~~~~

    • This suggests $sr has not opened the file. ($sr is equal to $null so can’t call $sr.ReadLine) The same error on $line.StartsWith suggests $line is $null as nothing was read into the file.

  4. Fred says:

    Awesome little script

  5. Fred says:

    I did have to remove the last line (415) and for any noobs – Open the script with PowerShell ISE and run it once (press the play button) then use the syntax Convert-Reg2Xml regPath\input.reg xmlPath\output.xml

    e.g.
    Convert-Reg2Xml D:\CoolPowerShell\input.reg D:\CoolPowerShell\output.xml
    where input.reg is your exported registry key that you want to convert.

    Thanks again….

  6. paul says:

    Hello! Thanks a lot for your idea to write that script, it’s realy despairing with the wizard.
    The link with the scirpt is no longer online. I saved the script text in a ps1 file and executed (Convert-Reg2Xml.ps1 D:\CoolPowerShell\input.reg D:\CoolPowerShell\output.xml). now i have a lots and a lots of errors. Can someone explain how to use the script correct and which line in the script must be changed?

  7. Muskiier says:

    Thanks Chentiangemalc for the work on this – it is a real timesaver! The link above to the download is broken, so I posted it (slightly revised with parameter prompts) here: http://www.veitch.ca/wp-content/uploads/2015/08/Convert_Reg_To_XML.zip . If you use the version above as noted by Roadie_UK it is duplicated after line 415 so copy and paste into your favourite text editor or the Powershell IDE and delete everything after line 415. Also remove the arguments on line 415 or revise them with your own correct paths pointing to your input and output file names. Eg. Convert-Reg2Xml -regPath “C:\temp\Exported_Settings.reg” -xmlPath “C:\temp\Converted_RegSettings.xml”.

  8. kop says:

    Perfect script.

    Any suggests how to import XML into GPMC thru powershell?

  9. Ronnie says:

    Thanks chentiangemale, and Muskiier – just what I needed.

  10. Armen says:

    Awesome Script! Any way of removing the Collections, so when you import into Group Policy it doesn’t import the collections as folders?

  11. Doug says:

    Nice script sir. FYI a problem I ran into with a registry entry for a encrypted password with a number of extended ascii characters in it. Looks I’ll have to stick with scripting using regedit instead of doing this using group policy.

    .\RegToXML.ps1 C:\temp\bmrpwdr.reg c:\temp\output.xml
    C:\temp\BMrpwdr.reg
    Name = ‘ConnectStringPWD’ Value = ‘¡¸à²Ï›Áç!å¬ÕL’
    Exception calling “WriteAttributeString” with “2” argument(s): “”, hexadecimal value 0x1D, is an invalid character.”
    At C:\temp\RegToXML.ps1:192 char:21
    + $xml.WriteAttributeString(“value”,$value)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentException

    Exception calling “WriteEndElement” with “0” argument(s): “The Writer is closed or in error state.”
    At C:\temp\RegToXML.ps1:193 char:21
    + $xml.WriteEndElement()
    + ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : InvalidOperationException

  12. Jorn Grotnes says:

    Thanks for this, very helpful. Note that the original Onedrive copy is gone, there is a zip download someone made, or just copy the 2 first functions (not the whole text!) from the textbox above into a file e.g. reg2xml.ps1. Then run powershell, “dot” the file (as in . .\reg2xml.ps1). Should give no errors. Then use Convert-Reg2XML function with the correct parameters. And note that with standard UAC you cannot drag and drop in the direction of GPMC (although you can drag *out* settings), but it works perfectly with copy (the XML file) and paste (into the preferences registry).

  13. Brian says:

    Excellent script, thanks very much. FYI, I’ve run into some instances where a {default} value is actually a REG_MULTI_SZ or a REG_EXPAND_SZ, so I had to modify your code to account for that:
    # read binary key to end
    while ($line.EndsWith(“\”))
    {
    $line=$line.Substring(0,$line.Length-1)+$sr.ReadLine().Trim()
    }

    # Account for whether the REG_MULTI_SZ is a Default value
    $default=”0″
    if ($line.StartsWith(“@=”))
    {
    $valueName=””
    $i = 0
    $default=”1″
    }
    else
    {
    $i = $line.IndexOf(‘”=hex(7):’)
    $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1)
    }

    ——————————————————————————————

    # Account for whether the REG_EXPAND_SZ is a default value
    $default=”0″
    if ($line.StartsWith(“@=”))
    {
    $valueName=””
    $i = 0
    $default=”1″
    }
    else
    {
    $i = $line.IndexOf(‘”=hex(2):’)
    $valueName=Convert-RegEscapeCodes $line.Substring(1,$i-1)
    }

  14. Marko Mård says:

    This creates keys with “Update” as action? So if one wants “Create”, do I just replace U with C? $action = “U”

    • It’s a while since I looked at this but I think so, you can always create a group policy preference manually first for a single item in group policy management console and just check the output XML it generates, that is pretty much how I built the tool.

Leave a comment