2
votes

I have a script that require 2 arrays as input, and optional logname :

#file:test.ps1
Param(
    [string[]]$array1,
    [string[]]$array2,
    [string]$logName = "log{0}.csv" -f (get-date -format "yyyyMMdd")
)

"array1: {0}" -f ($array1 -join " ")
"array2: {0}({1})" -f ($array2 -join " ") ,$array2.count
"logName: {0}" -f $logName

When run from a PowerShell console, everything is fine:

PS D:\temp> .\test.ps1 -array1 one,two -array2 1,2,3
array1: one two
array2: 1 2 3(3)
logName: log20190723.csv

But when run by calling powershell.exe (for scheduled task), only first element from array is grabbed, the rest is passed to the logname parameter.

PS D:\temp> powershell.exe -F D:\temp\test.ps1 -array1 one,two -array2 1,2,3
array1: one
array2: 1(1)
logName: two

How should I define params to grab all params into the array?

(BTW: I'm using PS4.0, with same result on Windows 2008 and 2012)

2

2 Answers

3
votes

TL;DR: You cannot pass PowerShell arrays across process boundaries.


The first invocation of your script runs within the current PowerShell process, hence one,two and 1,2,3 are passed as PowerShell arrays.

The second invocation of your script launches a second PowerShell process as an external program, thus taking a detour leaving and re-entering PowerShell. Because of that one,two and 1,2,3 are passed to the second PowerShell process as strings, not as arrays, since Windows doesn't know anything about PowerShell arrays.

You could split the parameter values at commas at the beginning of your script to mitigate this limitation:

Param(
    [string[]]$array1,
    [string[]]$array2,
    [string]$logName = "log{0}.csv" -f (Get-Date -Format "yyyyMMdd")
)

if ($array1.Count -eq 1) { $array1 = $array1.Split(',') }
if ($array2.Count -eq 1) { $array2 = $array2.Split(',') }

Note, however, that this might cause problems when you're passing a single argument that contains commas.


Addendum: the behavior you describe for the second invocation should only occur when you have whitespace before or after a comma:

PS C:\> powershell.exe -F C:\path\to\test.ps1 -array1 one, two -array2 1, 2, 3
array1: one
array2: 1(1)
logName: two

Otherwise the output should be like this:

PS C:\> powershell.exe -F C:\path\to\test.ps1 -array1 one,two -array2 1,2,3
array1: one,two
array2: 1,2,3(1)
logName: log20190723.csv
2
votes

Use -c instead of -f (command instead of file) (or use neither):

powershell.exe -c D:\temp\test.ps1 -array1 one,two -array2 1,2,3

array1: one two
array2: 1 2 3(3)
logName: log20190723.csv