Passing array to another script with Invoke-Command
Asked Answered
C

3

9

I'm stuck trying to figure this out. I've seen the other articles and have tried everything, but I'm not getting anywhere. I am trying to pass an array as an argument to another PS script. Here's what I'm trying:

$IPArray = Get-Content C:\ListofIps.txt
Invoke-Command -Computername $server -Credential $cred -FilePath "C:\script.ps1" -ArgumentList (,$IPArray)

The 5 values in $IPArray aren't being passed to the script that I call.

Thanks in advance, guys, I really appreciate any help you can give...

Crewelwork answered 10/7, 2013 at 18:0 Comment(6)
Why do you have a comma before $IPArray and why are you putting it in parentheses? If you just want to pass $IPArray as the argument list, use -ArgumentList $IPArray.Pankhurst
Thanks for the quick reply, Adi. According to this thread, the parenthesis and comma are required for -ArgumentList to view the argument as an array. I tried it both ways, however, and neither worked.Crewelwork
Does script.ps1 have a param() statement to accept the argument(s)? Try testing this by putting the following in a test.ps1 file on $server: param([string[]$IPs) $IPS | Write-Output That should at least tell if you the argument is getting passed and accepted properly by the target script.Run
Looks like that was it, JBSmith! I had tried the param statement earlier but didn't realize it had to be the first executable line in the second script. This is getting me what I need, but should I even have to pass the $IPArray as an -ArgumentType? Shouldn't it be in scope as a global variable when the test.ps1 script is called?Crewelwork
$IPArray is in the global scope in your current, local session. But when you run Invoke-Command you are launching a new, fresh session on the remote computer. That computer doesn't have any of the local variables, functions, modules, etc from your local session in it. In powershell version 3, there's a new variable "scope" called using that can pass local variables to remote sessions. So then you would specify the variable in your script like this: "$using:IPArray". But in version 2 you must use -ArgumentList to get the local variables to the remote machine.Run
Jobs have the same limitation. They seem related.Watchman
L
14

Use:

... -ArgumentList (,$IPArray)

Because the ArgumentList parameter expects an array you've correctly noted that you need to wrap the array in another array. However, the correct syntax in this scenario (specifying a parameter value) is to use a grouping expression () to create the nested array.

Leomaleon answered 10/7, 2013 at 22:12 Comment(2)
The first comma is not necessary if you use @($IPArray).Tericaterina
@() does nothing to an array. That is, if the contents of @() are a scalar then that scalar is put in array but if the contents are already an array, that array is not wrapped in an additional array.Leomaleon
V
1

This is an old question, but I'm going to re-iterate @keith-hill on the answer--add a comma at the beginning of the array declaration (even when including an existing array).

It's stupid, but I'm answering again because I tried all alternatives and that's the only thing that works--even with PowerShell 3.0+. You can use #require for anything from at least v3.0+, but nothing will work unless you do what @keith-hill suggests--even though it's an array, and the parameter is an array, PS sucks in this case (and I love PS)...do what he said (posting didn't work, so sorry but working answers are better): \ ... -ArgumentList (,$IPArray)

It makes no sense, but that works. Hands down to the PS team for dropping the bomb on this one, but if I hadn't done that my script would be null and void. And I've become the "scripting guy"...so here you go.

Vintager answered 12/7, 2017 at 0:0 Comment(2)
REALLY wanted to edit that, but in all honesty your fix doesn't work ...maybe for you, but not for everyone else. I'd love to hear about your problem though...Vintager
It's not really stupid. What's going on is, -ArgumentList by default takes an array and spreads the items out to the params in the invoked command: Invoke-Command -ScriptBlock { param($x, $y, $z) ... } -ArgumentList (1, 2, 3) sets $x to 1, $y to 2 $y, $z to 3. So, -ArgumentList already has special array handling; it's fundamentally how it works. When you pass in your own array, it can't tell the difference between yours and e.g. (1, 2, 3), so it takes your array items and distributes them. The (, $x) syntax makes it get an array with 1 element, and that element is your array.Sauer
C
1

If you are just trying to pass one array, you can treat the $args variable itself as the array in your remote command and you get the same result as passing it as (, $IPArray) and then accessing that array in the scriptblock as $args[0]. I didn't test whether this works with multiple arrays or not.

That is to say,

$MyScriptBlock = { $args | % { Do-Stuff -Thing $PSItem } }
Invoke-Command -Session $MySession -ScriptBlock $MyScriptBlock -ArgumentList $IPArray

will return the same values as

$MyScriptBlock = { $args[0] | % { Do-Stuff -Thing $PSItem } }
Invoke-Command -Session $MySession -ScriptBlock $MyScriptBlock -ArgumentList (,$IPArray)
Charil answered 1/5, 2021 at 8:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.