Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
385 views
in Technique[技术] by (71.8m points)

c# - Passing string[] from batch file (which contains double quotes ") to powershell script

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 element
  • If 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, and three, 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:

    • decorate the array parameter with attribute [Parameter(ValueFromRemainingArguments)]
    • and to pass the array elements as individual, space-separated arguments, without their parameter name.

In your case:

  • Declare the parameter:

    [Parameter(ValueFromRemainingArguments)]
    [string[]] $ScriptArgs
    
  • Invoke the script with separate, space-separate arguments not preceded by the parameter name to bind them as an array to $ScriptArgs:

    powershell -File Foobar.ps1 "-versn="1.0.0.0"" "pattern="FooBar.*""
    
    • 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:

powershell -command "./Foobar.ps1 '-versn="1.0.0.0"', '-pattern="FooBar.*"'"

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.

      • Additionally, if the script path contains whitespace or other shell metacharacters, you must quote it and invoke it via &, 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.

      • Given that the overall command must be passed inside "...", 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 `$.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...