Last active
November 9, 2024 22:58
-
-
Save realslacker/b400d7c0ccc22e93573c1a31dab4d8aa to your computer and use it in GitHub Desktop.
Converts a .REG file into an XML document that is compatible with GPO preferences. The registry file can contain updates or deletions. The resulting XML file can be copy and pasted, or drag and dropped onto the GPO preferences registry window to import the file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Converts a .REG file into an XML document that is compatible with GPO | |
preferences. | |
.DESCRIPTION | |
Converts a .REG file into an XML document that is compatible with GPO | |
preferences. The registry file can contain updates or deletions. The | |
resulting XML file can be copy and pasted, or drag and dropped onto the | |
GPO preferences registry window to import the file. | |
.PARAMETER RegistryFile | |
The path to the registry file to convert. Accepts pipline input. | |
.PARAMETER Destination | |
Output path of the XML files. Defaults to the CWD. | |
.PARAMETER Description | |
The description for the containers generated. | |
.PARAMETER UpdateMode | |
The update mode the registry settings should use. Options are 'Update', | |
'Create', and 'Replace'. | |
.INPUTS | |
[System.IO.FileSystemInfo] | |
[String] | |
.OUTPUTS | |
[System.IO.FileSystemInfo] | |
.NOTES | |
This is a complete re-write of the Reg2Xml by Malcolm McCaffery. The original script is | |
available at http://chentiangemalc.wordpress.com. | |
New in this script: | |
- Cleaned up and simplified logic | |
- Support for deleting keys using native REG file settings | |
- Support for pipeline input | |
This script is released as-is, with no warranty. Use at your own risk. | |
.LINK | |
https://gist.github.com/realslacker/b400d7c0ccc22e93573c1a31dab4d8aa/raw/ | |
#> | |
function Convert-RegToXml { | |
[CmdletBinding()] | |
Param( | |
[Parameter(Mandatory=$true, Position=1, ValueFromPipeline)] | |
[ValidateScript({Test-Path $_})] | |
[string[]] | |
$RegistryFile, | |
[Parameter(Mandatory=$false, Position=2)] | |
[ValidateScript({Test-Path $_ -PathType Container})] | |
[string] | |
$Destination='.', | |
[string] | |
$Description="Imported $(Get-Date -Format 'yyyy-MM-dd')", | |
[ValidateSet('Update','Create','Replace')] | |
[string] | |
$UpdateMode='Update' | |
) | |
begin { | |
$ErrorActionPreference = 'Stop' | |
$UpdateAction = $UpdateMode.Substring(0,1) | |
$XmlSettings = New-Object System.Xml.XmlWriterSettings | |
$XmlSettings.Indent = $True | |
$XmlSettings.Encoding = [System.Text.Encoding]::UTF8 | |
} | |
process { | |
foreach ( $RegItem in $RegistryFile ) { | |
Write-Verbose "Processing '$RegItem'..." | |
$RegItem = Get-Item $RegItem | |
if ( $RegItem.Extension -ne '.reg' ) { | |
throw [System.IO.FileFormatException]::new("File is not a REG file") | |
} | |
if ( Test-Path -Path ( Join-Path $Destination "$($RegItem.BaseName).xml" ) -PathType Leaf ) { | |
if ( ( Read-Host "The file '$($RegItem.BaseName).xml' already exists, overwrite? [y/N]" ) -match '^y' ) { | |
$XmlPath = Get-Item -Path ( Join-Path $Destination "$($RegItem.BaseName).xml" ) | |
echo '' > $XmlPath | |
} else { | |
Write-Error "Please specify an output folder with -Destination or move the existing file" | |
} | |
} else { | |
# start the XML document | |
$XmlPath = New-Item -Path ( Join-Path $Destination "$($RegItem.BaseName).xml" ) -ItemType File | |
} | |
# start the XML writer | |
$XmlWriter = [System.Xml.XmlWriter]::Create($XmlPath, $XmlSettings) | |
# create the RegistrySettings node | |
$XmlWriter.WriteStartElement('Collection') | |
$XmlWriter.WriteAttributeString('clsid', '{53B533F5-224C-47e3-B01B-CA3B3F3FF4BF}') | |
$XmlWriter.WriteAttributeString('name', $RegPath ) | |
$XmlWriter.WriteAttributeString('descr', $Description ) | |
# read in the registry file | |
$RegContents = Get-Content $RegItem -Raw | |
# put multiline values on one line | |
$RegContents = $RegContents -replace '\\[\r\n]+\s+', '' | |
# split by lines | |
$RegContents = $RegContents -split '[\r\n]+' | |
# init the collection count | |
$RegCollectionOpen = $false | |
switch -Regex ($RegContents) { | |
# KEY | |
'^\[(-?)(([^\\]+)\\(.*))\]$' { | |
$RegPath = $Matches[2] | |
$RegHive = $Matches[3] | |
$RegKey = $Matches[4] | |
Write-Verbose "Hive: $RegHive" | |
Write-Verbose "Key: $RegKey" | |
if ($RegCollectionOpen) { $XmlWriter.WriteEndElement() } | |
$XmlWriter.WriteStartElement('Collection') | |
$XmlWriter.WriteAttributeString('clsid', '{53B533F5-224C-47e3-B01B-CA3B3F3FF4BF}') | |
$XmlWriter.WriteAttributeString('name', $RegPath ) | |
$XmlWriter.WriteAttributeString('descr', $Description ) | |
# are we deleting a registry key? | |
if ( $Matches[1] -eq '-' ) { | |
Helper-WriteRegItemXML -XmlWriter $XmlWriter ` | |
-Hive $RegHive ` | |
-Key $RegKey ` | |
-Delete | |
} | |
$RegCollectionOpen = $true | |
} | |
# Delete (default) | |
'^@=-$' { | |
Helper-WriteRegItemXML -XmlWriter $XmlWriter ` | |
-Hive $RegHive ` | |
-Key $RegKey ` | |
-Default ` | |
-Delete | |
} | |
# Delete named value | |
'^"(.+)"=-$' { | |
Helper-WriteRegItemXML -XmlWriter $XmlWriter ` | |
-Hive $RegHive ` | |
-Key $RegKey ` | |
-Name $Matches[1] ` | |
-Delete | |
} | |
# REG_SZ (default) | |
'^@="(.*)"$' { | |
Helper-WriteRegItemXML -XmlWriter $XmlWriter ` | |
-Hive $RegHive ` | |
-Key $RegKey ` | |
-Default ` | |
-Value $Matches[1] ` | |
-UpdateAction $UpdateAction | |
} | |
# REG_SZ | |
'^"(.+)"="(.*)"$' { | |
Helper-WriteRegItemXML -XmlWriter $XmlWriter ` | |
-Hive $RegHive ` | |
-Key $RegKey ` | |
-Name $Matches[1] ` | |
-Value $Matches[2] ` | |
-UpdateAction $UpdateAction | |
} | |
# REG_BINARY | |
'^"(.+)"=hex:(.*)$' { | |
$BinaryValue = $Matches[2] -replace '[^0-9a-f]', '' | |
Helper-WriteRegItemXML -XmlWriter $XmlWriter ` | |
-Hive $RegHive ` | |
-Key $RegKey ` | |
-Name $Matches[1] ` | |
-Value $BinaryValue ` | |
-Type REG_BINARY ` | |
-UpdateAction $UpdateAction | |
} | |
# REG_DWORD | |
'^"(.+)"=dword:(.*)$' { | |
$DWordValue = $Matches[2].ToUpper() | |
Helper-WriteRegItemXML -XmlWriter $XmlWriter ` | |
-Hive $RegHive ` | |
-Key $RegKey ` | |
-Name $Matches[1] ` | |
-Value $DWordValue ` | |
-Type REG_DWORD ` | |
-UpdateAction $UpdateAction | |
} | |
# REG_QWORD | |
'^"(.+)"=hex\(b\):(.*)$' { | |
$QWordValue = $Matches[2].ToUpper().Split(',') | |
[array]::Reverse($QWordValue) | |
$QWordValue = $QWordValue -join '' | |
Helper-WriteRegItemXML -XmlWriter $XmlWriter ` | |
-Hive $RegHive ` | |
-Key $RegKey ` | |
-Name $Matches[1] ` | |
-Value $QWordValue ` | |
-Type REG_QWORD ` | |
-UpdateAction $UpdateAction | |
} | |
# REG_MULTI_SZ | |
'^"(.+)"=hex\(7\):(.*)$' { | |
$MulitStringValue = $Matches[2].ToUpper().Split(',') | |
$RegBytes = [byte[]]::New( $MulitStringValue.Count ) | |
for( $i=0; $i -lt $MulitStringValue.Count; $i++) { | |
$RegBytes[$i] = [convert]::ToByte( $MulitStringValue[$i], 16 ) | |
} | |
$MulitStringValue = [System.Text.Encoding]::Unicode.GetString( $RegBytes ) -replace '\0\0$','' -split '\0' | |
Helper-WriteRegItemXML -XmlWriter $XmlWriter ` | |
-Hive $RegHive ` | |
-Key $RegKey ` | |
-Name $Matches[1] ` | |
-Value $MulitStringValue ` | |
-Type REG_MULTI_SZ ` | |
-UpdateAction $UpdateAction | |
} | |
# REG_EXPAND_SZ | |
'^"(.+)"=hex\(2\):(.*)$' { | |
$ExpandStringValue = $Matches[2].ToUpper().Split(',') | |
$RegBytes = [byte[]]::New( $ExpandStringValue.Count ) | |
for( $i=0; $i -lt $ExpandStringValue.Count; $i++) { | |
$RegBytes[$i] = [convert]::ToByte( $ExpandStringValue[$i], 16 ) | |
} | |
$ExpandStringValue = [System.Text.Encoding]::Unicode.GetString( $RegBytes ) -replace '\0$','' | |
Helper-WriteRegItemXML -XmlWriter $XmlWriter ` | |
-Hive $RegHive ` | |
-Key $RegKey ` | |
-Name $Matches[1] ` | |
-Value $ExpandStringValue ` | |
-Type REG_EXPAND_SZ ` | |
-UpdateAction $UpdateAction | |
} | |
} | |
# if we have an open collection close it | |
if ($RegCollectionOpen) { $XmlWriter.WriteEndElement() } | |
# close the RegistrySettings node | |
$XmlWriter.WriteEndElement() | |
# close the XML file | |
$XmlWriter.Close() | |
Write-Verbose "Xml File: $XmlPath" | |
# output the resulting file handle | |
Get-Item -Path $XmlPath | |
} | |
} | |
} | |
function Helper-WriteRegItemXML { | |
param( | |
[Parameter(Mandatory=$true, ValueFromPipeline)] | |
[System.Xml.XmlWriter] | |
$XmlWriter, | |
[Parameter(Mandatory=$true)] | |
[ValidateSet('HKEY_CLASSES_ROOT', 'HKEY_CURRENT_USER', 'HKEY_LOCAL_MACHINE', 'HKEY_USERS', 'HKEY_CURRENT_CONFIG')] | |
[string] | |
$Hive, | |
[Parameter(Mandatory=$true)] | |
[string] | |
$Key, | |
[Parameter(ParameterSetName='Delete')] | |
[Parameter(ParameterSetName='DefaultKey')] | |
[switch] | |
$Default, | |
[Parameter(ParameterSetName='Delete')] | |
[switch] | |
$Delete, | |
[Parameter(ParameterSetName='Delete', Mandatory=$false)] | |
[Parameter(ParameterSetName='NamedKey', Mandatory=$true)] | |
[string] | |
$Name='', | |
[Parameter(ParameterSetName='NamedKey')] | |
[ValidateSet('REG_SZ', 'REG_BINARY', 'REG_DWORD', 'REG_QWORD', 'REG_MULTI_SZ', 'REG_EXPAND_SZ')] | |
[string] | |
$Type='REG_SZ', | |
[Parameter(ParameterSetName='DefaultKey')] | |
[Parameter(ParameterSetName='NamedKey')] | |
[string[]] | |
$Value='', | |
[Parameter(ParameterSetName='DefaultKey', Mandatory=$true)] | |
[Parameter(ParameterSetName='NamedKey', Mandatory=$true)] | |
[ValidateSet('C', 'R', 'U')] | |
[string] | |
$UpdateAction | |
) | |
# Default value | |
if ( $Default.IsPresent ) { | |
$RegName = $RegKey.Split('\\')[-1] | |
$RegStatus = '(Default)' | |
$Name = '' | |
} | |
# Named value | |
elseif ( -not [string]::IsNullOrEmpty( $Name ) ) { | |
$RegName = $Name | |
$RegStaus = $Name | |
} | |
# Registry key | |
else { | |
$RegName = $RegKey.Split('\\')[-1] | |
$RegStatus = $RegKey.Split('\\')[-1] | |
$Name = '' | |
} | |
$XmlWriter.WriteStartElement('Registry') | |
$XmlWriter.WriteAttributeString('clsid', '{9CD4B2F4-923D-47f5-A062-E897DD1DAD50}' ) | |
$XmlWriter.WriteAttributeString('name', $RegName ) | |
$XmlWriter.WriteAttributeString('status', $RegStatus ) | |
$XmlWriter.WriteAttributeString('image', 7 ) | |
$XmlWriter.WriteAttributeString('changed', (Get-Date -Format 'yyyy-MM-dd HH:mm:ss') ) | |
$XmlWriter.WriteAttributeString('uid', "{$(New-Guid)}" ) | |
$XmlWriter.WriteStartElement('Properties') | |
$XmlWriter.WriteAttributeString('action', $( if ( $Delete.IsPresent ) { 'D' } else { $UpdateAction } ) ) | |
$XmlWriter.WriteattributeString('displayDecimal', '0' ) | |
$XmlWriter.WriteattributeString('default', $( if ( $Default.IsPresent ) { '1' } else { '0' } ) ) | |
$XmlWriter.WriteAttributeString('hive', $Hive ) | |
$XmlWriter.WriteAttributeString('key', $Key ) | |
$XmlWriter.WriteattributeString('name', $Name ) | |
$XmlWriter.WriteattributeString('type', $Type ) | |
if ( $Type -eq 'REG_MULTI_SZ' ) { | |
$XmlWriter.WriteAttributeString('value', $Value -join ' ') | |
$XmlWriter.WriteStartElement('Values') | |
$Value | ForEach-Object { | |
$XmlWriter.WriteStartElement('Value') | |
$XmlWriter.WriteString($_) | |
$XmlWriter.WriteEndElement() | |
} | |
$XmlWriter.WriteEndElement() | |
} | |
else { | |
$XmlWriter.WriteAttributeString('value', $Value ) | |
} | |
$XmlWriter.WriteEndElement() | |
$XmlWriter.WriteEndElement() | |
} | |
Export-ModuleMember -Function Convert-RegToXml |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment