I'm having some trouble ex/importing registry values with PowerShell, specifically with multivalue (REG_MULTI_SZ
) keys.
I have a test registry entry:
[HKEY_CURRENT_USER\SOFTWARE\my\Testkey] "string"="blub" "multi"=hex(7):6f,00,6e,00,65,00,00,00,74,00,77,00,6f,00,00,00,74,00,68,00,72,\ 00,65,00,65,00,00,00,00,00 "bin"=hex:11,11,11,11,10
Now if I do the following
$Hive = "HKCU:\SOFTWARE\my\Testkey"
$Property = (Get-ItemProperty -path $Hive)
$Property.PSObject.Properties |
select name, value, TypeNameOfValue |
Where-Object name -NotLike "PS*" |
Export-Clixml test.xml
$Prop = Import-Clixml .\test.xml
foreach ($i in $Prop) {
New-ItemProperty -Path $Hive -Name $i.Name -Value $i.Value
}
The value of the key in the registry is set to "System.Collections.ArrayList"
instead of its real value. It only seems to happen to multivalue keys.
I tried
New-ItemProperty -Path $Hive -Name $i.Name -Value ($i.Value | Out-String)
but that didn't work either. It seems like New-ItemProperty
doesn't convert the string arrays into the proper type. Anyone any idea what datatype to use/how to fix this?
Obviously I can use
foreach($i in $Prop){
if ($i.TypeNameOfValue -eq 'System.String[]') {
New-ItemProperty -Path $Hive -Name $i.Name -Value $i.Value -PropertyType "MultiString"
} else {
New-ItemProperty -Path $Hive -Name $i.Name -Value $i.Value
}
}
but I'd prefer to just convert $i.Value
to the proper datatype during ex- or import.
Or is there any other clever solution I overlooked?
You need to import the values with the correct type. Create a hashtable mapping the type of the imported data to the corresponding registry data type and look up the type name on import:
$regtypes = @{
'System.String' = 'String'
'System.String[]' = 'MultiString'
'System.Byte[]' = 'Binary'
}
foreach ($i in $Prop) {
New-ItemProperty -Path $Hive -Name $i.Name -Value $i.Value -Type $regtypes[$i.TypeNameOfValue]
}
An alternative would be casting the value to the imported type name:
foreach ($i in $Prop) {
New-ItemProperty -Path $Hive -Name $i.Name -Value ($i.Value -as $i.TypeNameOfValue)
}
Note that passing the imported type name via the -Type
parameter does not work for all types.