how to use sub-Array notation to specify variables in remote sessions?

I’m trying to create a script that will query the registry on remote machines.

I’m running into difficulty when trying to parametrize the keys and values to query.

My thought is to specify the key/value as an array of 2-tuples, e.g.,

.\Query-Registry.ps1 -hosts $hosts -RegItems (“HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings”,“ProxyServer”),(“HKLM:\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings”,“ProxySettingsPerUser”)

 

The script as I have it so far ‘would’ work but apparently the matrix notation isn’t allowed with the ‘$using:variable’ notation. How can I achieve this with other notation?

Many thanks!

Here is my script:

----------------

param (

[Parameter(Mandatory=$true)][string] $Hosts,

[string] $RegItems =((“HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings”,“ProxyServer”),(“HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings”,“AutoConfigUrl”))

)

$IC = Invoke-Command -ComputerName $Hosts -ThrottleLimit 128 -ScriptBlock {

$RegResult = Â @()

$splat = @{}

for ($i=0; $i -lt $using:RegItems.count; $i++) {

$splat[$using:RegItems[$i][0] + " | " + $using:RegItems[$i][1]] = (Get-ItemProperty -Path $using:RegItems[$i][0] -Name $using:RegItems[$i][1]).$using:RegItems[$i][1]

}

$RegResult += New-Object PSObject -Property $splat

$RegResult

} Â -ErrorVariable errmsg 2>$null

 

Always peel back the onion so that you can see what is actually happening.

First, look at the collection you create:

PS C:> [string] $RegItems =((“HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings”,“Pro
xyServer”),(“HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings”,“AutoConfigUrl”))
PS C:> $RegItems.GetType()

IsPublic IsSerial Name BaseType


True True String System.Array

That shows you that you created a one-dimensional array of type String. Now look at the contents:

PS C:> $RegItems[0]
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings ProxyServer
PS C:> $RegItems[1]
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings AutoConfigUrl

This confirms the values in each position in that array. You can see here that your array is not created as you expected it to be. Back to the drawing board, try this way:

PS C:> [string]$RegItems =((“HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings”,“ProxyServer”),(“HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings”,“AutoConfigUrl”))

The key difference here is making sure you identify that you are creating an array of arrays of strings.

Next, try passing that array to a “remote” system (the local machine):

PS C:> Invoke-Command -ComputerName localhost -ScriptBlock {$using:RegItems}
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings
ProxyServer
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings
AutoConfigUrl

That works, so what if you want to access a property of those values:

PS C:> Invoke-Command -ComputerName localhost -ScriptBlock {$using:RegItems.GetType().FullName}
At line:1 char:54

  • Invoke-Command -ComputerName localhost -ScriptBlock {$using:RegItems.GetType().F …
  •                                                  ~~~~~~~~~~~~~~~~~~~~~~~~~
    

Expression is not allowed in a Using expression.
+ CategoryInfo : ParserError: (:slight_smile: , ParentContainsErrorRecordException
+ FullyQualifiedErrorId : InvalidUsingExpression

Ok, so “using” doesn’t allow that. But we can do it if we use parentheses:

PS C:> Invoke-Command -ComputerName localhost -ScriptBlock {($using:RegItems).GetType().FullName}
System.Collections.ArrayList

Now you can see that on the other side (on the “remote” system), the array was received as an array list. What about individual items in the array list:

PS C:> Invoke-Command -ComputerName localhost -ScriptBlock {$using:RegItems[0]}
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings
ProxyServer

Yup, works. And getting a specific item in one of those arrays:

PS C:> Invoke-Command -ComputerName localhost -ScriptBlock {$using:RegItems[0][1]}
ProxyServer

Now that you verified each of the pieces, you can make your script work.

Excellent response! Thank you for teaching me how to fish rather than just giving me the fish.

My script is now working as desired.