I have a powershell script which has a string[]
parameter and try to pass value to this from batch file
PowerShell Script
[string[]]$ScriptArgs
Batch File
powershell -File Foobar.ps1 -ScriptArgs -versn="""1.0.0.0""",pattern="""FooBar.*"""
(3 Quotes - For escaping/showing 1 quote)
But no matter what I do Write-Host $ScriptArgs.Count
prints 1
I want the variable to receive 2 elements
[0]
will be -versn="1.0.0.0"
[1]
will be -pattern="FooBar.*"
In batch file, I even tried setting variables individually
set @sArgs = -versn="""1.0.0.0"""
set @sArgs = %sArgs%;-pattern="""FooBar.*"""
powershell -File Foobar.ps1 -ScriptArgs %sArgs%
but the console somehow runs as if the variable is not created and run it as
powershell -File Foobar.ps1 -ScriptArgs
and throws error
Missing an argument for parameter 'ScriptArgs'. Specify a parameter of type
System.String[]
and try again
What should I change to achieve this?
When calling a PowerShell script from from a batch file (from
cmd.exe
) with-File
, there is no way to directly pass an array of values to a PowerShell array parameter:If you specify the array values without spaces, they are considered a SINGLE element; e.g.:
one,two,three
becomes a SINGLE array elementIf you do use spaces, the trailing commas become part of the arguments, and only the FIRST value is bound to the array parameter:
one, two, three
-one,
- including the trailing,
- becomes the only array element,two,
andthree,
are considered separate arguments.The workarounds are to:
Either: use
-Command
to invoke the script - see bottom section.Or, with
-File
, declare the parameter differently and pass arguments differently:[Parameter(ValueFromRemainingArguments)]
In your case:
Declare the parameter:
Invoke the script with separate, space-separate arguments not preceded by the parameter name to bind them as an array to
$ScriptArgs
:Note the quoting:
Each argument as a whole is enclosed in
"..."
- this isn't strictly necessary, but guards against-
-prefixed values such as-version
being mistaken for parameter names."
chars. to be retained as literals are\
-escaped (which contrasts with the`
-escaping that must be used from within PowerShell).The inherent limitations of this approach:
The approach doesn't support multiple array parameters, because only one can be decorated with
ValueFromRemainingArguments
.You cannot pass any other arguments positionally (i.e., you must precede arguments to pass to other parameters with their parameter name).
Alternative: Using
-Command
instead of-File
:Note:
What you pass to
-Command
is treated as a piece of PowerShell code - whether you pass a single argument or multiple ones - in the latter case, they are simply concatenated with spaces and the result is then interpreted as PowerShell code.The implications are:
To execute a script in the current directory, you must refer to it with a path (
.\
) - in order to execute it.&
, the call operator; e.g.,& '.\Foo Bar.ps1'
You can pass array arguments as usual, except that
"
chars. must again be escaped as\"
, not`"
.Also note that again the arguments are quoted as a whole (too), which in this is case required to prevent PowerShell from interpreting
-versn
and-pattern
as parameter names."..."
, performing the embedded quoting with"
, which still possible, is quite awkward, because you then have to combine\
- and`
-escaping; e.g.,\"-pattern=`\"FooBar.*`\"\"
Generally, be aware that all usual PowerShell parsing rules apply, so that, for instance, to use a literal
$
, you must escape it as`$
.