I am trying to figure out a way to pass an array to a named parameter in a separate script. However, I could not find any solution.
Test2.ps1:
param(
[int]$a,
[int]$b,
[int]$c,
[string[]]$d
)
write-host "`$a = $a"
write-host "`$b = $b"
write-host "`$c = $c"
write-host "`$d:" -nonewline
foreach($str in $d) {
write-host " $str" -nonewline
}
write-host
Main script:
$arr = @("abc", "def", "ghi")
$params = @{
a = 1;
b = 2;
c = 3;
d = $arr
}
#invoke-command -filepath "test2.ps1" -ArgumentList 1,2,3,@("abc", "def", "ghi")
$scriptPath = "test2.ps1"
$sb = [scriptblock]::create(".{$(get-content $ScriptPath -Raw)} $(&{$args} @params)")
invoke-command -scriptblock $sb
When executed, I got output that
$d:System.Object[]
The line below was copied from another Stackoverflow answer but I don't quite understand how it worked for the first 3 named parameters.
$sb = [scriptblock]::create(".{$(get-content $ScriptPath -Raw)} $(&{$args} @params)")
Especially the "$(&{$args} @params)" part. I have basic understanding of splatting, but this is beyond me. Much appreciated if someone can explain the syntax a bit for me.
When you put @params
inside an expandable string, you're forcing the parser to convert the resulting output to a string, and the default behavior of ToString()
(if not overridden) is to just return the type name of the object in question.
Simply wait until you call the script before you supply the parameters:
$sb = [scriptblock]::Create("$(get-content $ScriptPath -Raw)")
& $sb $args @params
or, if you want to dot-source the script with specific parameters:
$sb = [scriptblock]::Create("$(get-content $ScriptPath -Raw)")
& {.$sb $args @params}