Sometimes an Apple is an Orange

I was helping a member out in the PowerShell forum at ScriptingAnswers.com. He was trying to create a multistring registry entry on a remote computer using the .NET registry classes. Creating registry values is really not that complicated. Here’s a short example:

$computer="CHAOS"
$regpath="SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Computer)
$regKey= $reg.OpenSubKey($regpath,$True)
 
#create a new string value
$regKey.SetValue("MyTest","Sample Value","STRING")

You have to open the registry key for writing using $TRUE as the second parameter. The SetValue() method has several overloads. I’m using one where I specify the new registry value, its data and the value kind; in this case a string. I can also create DWORD,MultiString or Expandable string values as well.

Multistring implies an array, so first I thought all that was necessary would be to specify an array. But no.

PS C:\test> $regKey.SetValue(“MyMulti”,(“a”,”b”,”c”),”MULTISTRING”)
Exception calling “SetValue” with “3” argument(s): “The type of the value object did not match the specified RegistryValueKind or the object could not be properly converted.”
At line:1 char:17
+ $regKey.SetValue <<<< (“MyMulti”,(“a”,”b”,”c”),”MULTISTRING”)
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

I tried creating an array first.

PS C:\test> $arr=@(“a”,”b”,”c”)
PS C:\test> $regKey.SetValue(“MyMulti”,$a,”MULTISTRING”)

The error was the same. Then I had a thought to compare value from an existing multistring setting so I created one using REGEDIT and retrieved it in PowerShell.

PS C:\test> $sa=$regKey.GetValue(“sa”)
PS C:\test> $sa
lucky
daisy
ginger

It looked like an array.  Tested as an array. But so did mine.

PS C:\test> $sa -is [array]
True
PS C:\test> $arr -is [array]
True

I tried creating a new multistring registry value with $sa. To my surprise it worked!

PS C:\test> $regKey.SetValue(“MyMulti”,$sa,”MULTISTRING”)
PS C:\test> $regkey.GetValue(“MyMulti”)
lucky
daisy
ginger

Now I was really puzzled. I had two variables that both appeared to be arrays of strings, yet one failed . Then I tried this:

PS C:\test> $sa.getType()

IsPublic IsSerial Name       BaseType
——– ——– —-       ——–
True     True     String[]   System.Array

PS C:\test> $arr.GetType()

IsPublic IsSerial Name       BaseType
——– ——– —-       ——–
True     True     Object[]   System.Array

Did you catch the difference? The underlying system types were different. Now I knew what to do.

PS C:\test> [string[]]$arr=@(“a”,”b”,”c”)

PS C:\test> $regKey.SetValue(“MyMulti”,$arr,”MULTISTRING”)
PS C:\test> $regKey.GetValue(“MyMulti”)
a
b
c

I specifically cast $arr to be essentially a string of nested string. The registry was expecting simple strings, not string objects.

I was distracted by PowerShell’s display of my two variables. I thought I was comparing apples to apples, but one of them was actually an orange. If I was more of a developer, I might have figured this out sooner but it was a valuable lesson to not take things at face value.

If you have PowerShell questions or challenges, I hope you’ll join me in the forums at ScriptingAnswers.com.