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...

Sameer
  • 103
  • 1
  • 4
  • 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`. – Adi Inbar Jul 10 '13 at 18:34
  • 1
    Thanks for the quick reply, Adi. According to [this thread](http://stackoverflow.com/questions/7152740/how-to-pass-an-array-as-a-parameter-to-another-script), the parenthesis and comma are required for -ArgumentList to view the argument as an array. I tried it both ways, however, and neither worked. – Sameer Jul 10 '13 at 18:55
  • 1
    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. – jbsmith Jul 10 '13 at 19:02
  • 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? – Sameer Jul 10 '13 at 19:19
  • $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. – jbsmith Jul 10 '13 at 21:43
  • Jobs have the same limitation. They seem related. – js2010 Oct 30 '19 at 16:12

3 Answers3

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.

Keith Hill
  • 194,368
  • 42
  • 353
  • 369
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.

areyling
  • 2,181
  • 2
  • 20
  • 25
  • 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... – areyling Jul 12 '17 at 00:01
  • 1
    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_. – Jonathan Gilbert May 30 '19 at 17:40
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)