Need your help :). Im trying to convert Roger Zanders wonderful Reg2PS into my own Powershell script which i want to use in Intune for some comfortable Registry configs. Greetings at this point to RZ! https://reg2ps.azurewebsites.net/
I found his code here: https://github.com/rzander/Reg2CI/blob/master/Source/REG2PS/RegClass.cs
Relevant Codepart in this topic:
if (DataType == ValueType.MultiString)
{
//return Encoding.UTF8.GetString(Encoding.Unicode.GetBytes(_value.Replace("hex(7):", "").Replace(" ", "")));
string[] aHex = _value.Replace("hex(7):", "").Replace(" ", "").Split(',');
List<byte> bRes = new List<byte>();
foreach (string sVal in aHex)
{
bRes.Add(Convert.ToByte(sVal, 16));
}
string sResult = Encoding.Unicode.GetString(bRes.ToArray());
_svalue = "\"" + string.Join(",", sResult.TrimEnd('\0').Split('\0')) + "\"";
return sResult.TrimEnd('\0').Split('\0');
}
So after some other people tried to translate it or write it by there own, i recognize that Roger did it overall better with Multi_SZ (Whitespaces, "", and so on).
Therefore im fine with every Type but struggle at the Multi_SZ like so many.
I export a Registry Multi_SZ with Reg.exe.
Example:
$PlainValue = '"MultiStringProperty"=hex(7):56,00,61,00,6c,00,75,00,65,00,31,00,00,00,56,00,\61,00,6c,00,75,00,65,00,32,00,00,00,56,00,61,00,6c,00,75,00,65,00,33,00,00,\00,00,00'
# Get the Value itself
$Value = $PlainValue.Split("=")[1]
# Remove Hex Descrioption
$Value = $Value.Replace( "hex(7):","" )
# Learned from a HEX to UTF16 Converter the "\" is just ja reg.exe thing to shortening the Line in the File -> Remove!
$Value = $Value.Replace("\","")
And now the Problem begins. What worked for me is for Example:
$Value1 = $Value -split (",") | % { [INT]"0x$_" }
$Value1 = [Text.Encoding]::Unicode.GetString($Value1)
$Value2 = $Value -split (",") | % { [char][byte]"0x$_" }
$Value2 = $Value2 -join ''
My target is to have a final format of an String as: @("Value1","Value2","Value3")
Problem: The String i got in $Value1 or $Value2 isnt recognizing to .split(" ").
If i split before like:
# Splitting Hex Spaces
$Separator = ",00,00,00,"
$ArrValues = $Value -split $separator
$TempValues = @()
ForEach( $Val in $ArrValues )
{
$Temp = $Val -split (",") | % { [INT]"0x$_" }
[Text.Encoding]::Unicode.GetString($Temp)
$TempValues += [Text.Encoding]::Unicode.GetString($Temp)
}
Then PS has Problems to convert the Digits ...
Do i have some understanding problems or has powershell problems to convert the array? Im trying to find a better separation instead of 00,00,00 in the mean....
Please correct me but as i know in REG_Multi_SZ there is no witespace within the value allowed right?
I suggest a different approach based on
-replace, the regular-expression-based string replacement operator, in combination with-split(which is by default also regex-based), which is both more concise and efficient:Note:
-replace '^.+=hex\(7\):|\\'replaces everything up to and including=hex(7):as well as (|) any embedded\(escaped as\\) from the input string, leaving just the "hex-byte string"-split ','splits the byte string into individual bytes (represented as two-digit hex strings without a prefix)-replace '^', '0x'effectively prepends'0x'to each byte representation (^matches the position at the start of each individual byte, which is where0x, the substitution string is placed).The array of resulting strings (
@('0x56', '0x00', '0x61', ...)) is then automatically converted to[byte]values by PowerShell, due to the[byte[]]type constraint on the target variable,$bytes.[Text.Encoding]::Unicode.GetString($bytes)then converts the resulting byte array to the text it represents, based on interpreting the bytes as "Unicode" (UTF-16LE) encoded..TrimEnd("`0"`)removes the trailing NULL characters from the resulting text (REG_MULTI_SZstrings have two NULLs as terminators, to signal that no more strings are present).-split "`0"then splits the resulting string by the interior NULLs that separate the individual strings inside aREG_MULTI_SZstrings, yielding an array of those strings.As for what you tried:
Splitting
$Valueby,00,00,00,isn't a valid way to break the byte sequences into parts that form valid UTF-16LE byte sequences.ASCII-range Unicode characters, such as
Vor1, encoded as UTF-16LE have a0x0byte as the second byte in the two-byte sequence that forms a single character, and if you remove this byte (which is what your-splitoperation effectively does at the end of the substrings), you'll end up with an invalid character, which[Text.Encoding]::Unicode.GetString()represents as�, the REPLACEMENT CHARACTER, U+FFFD0x0only holds for characters in the ISO-8859-1 subrange of Unicode, i.e. only for Unicode code points in the 8-bit subrange,U+0000-U+00FF. For characters outside that range, say,€, that second byte is not0x0.You can avoid having to manually break the byte sequences by
0x0 0x0separators along proper character boundaries if you perform decoding via[Text.Encoding]::Unicode.GetString()first, on the entire string, and then split the resulting - properly parsed string - into substrings by NULL characters,U+0000), as shown in the solution at the top.