Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

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

chocolatey - Powershell "A positional parameter cannot be found that accepts argument"

I'm getting this below error trying to run this code and I'm not sure how to resolve it. Anyone ideas?

$ChocoPackage = "packagename"
$localprograms = choco list --localonly
Start-Process -Wait -FilePath "C:ProgramDatachocolateychoco.exe" -ArgumentList "install $ChocoPackage -ia "'/D=C:Program Filespackagename'" -y"
Start-Process : A positional parameter cannot be found that accepts argument '/D=C:Program Filespackagename'.
At C:Program Filesinstall.ps1:3 char:5
+     Start-Process -Wait -FilePath "C:ProgramDatachocolateychoco.ex ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Start-Process], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.StartProcessCommand
See Question&Answers more detail:os

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

1 Answer

0 votes
by (71.8m points)

Note:

  • As you point out in your own answer, special quoting requirements apply to cocho.exe's /ia parameter.
  • However, since you are using Start-Process, it is not the instructions from the linked page for PowerShell that apply in this case, but the ones for cmd.exe (even though there is no shell involved in this invocation; however, like cmd.exe, console applications themselves generally only understand "..." quoting); that is, your -ArgumentList string must end up containing the following verbatim, which is what the string passed to -ArgumentList below achieves via embedded " characters escaped as `" ("" would work too):
    "/D=""C:Program Filespackagename"""
Start-Process -Wait -FilePath "C:ProgramDatachocolateychoco.exe" `
  -ArgumentList "install $ChocoPackage -ia `"/D=`"`"C:Program Filespackagename`"`"`" -y"

Only if you call choco.exe directly from PowerShell do the PowerShell instructions apply ('/D=""C:Program Filespackagename""'):

& "C:ProgramDatachocolateychoco.exe" install $ChocoPackage -ia '/D=""C:Program Filespackagename""' -y

As for what you tried:

What you passed to -ArgumentList was composed of three directly adjoining string literals in the form " a "' b '" c ", to use a simplified example (i.e., a double-quoted string right next to single-quoted string, right next to another double-quoted string).

However, PowerShell doesn't fully support implicit concatenation of directly adjoining string literals to form a single argument the way that POSIX-compatible shells such as bash do; doing so results in the strings being passed as separate arguments, which caused your problem (Start-Process saw extra positional parameters after -ArgumentList it didn't expect).

To demonstrate the original problem with the simplified example:

PS> Write-Output " a "' b '" c "
 a 
 b 
 c 

That is, Write-Output received string literals " a ", ' b ', and " c " as 3 separate arguments (as implied by their appearing on their own line each).

Only if the first token is unquoted do you get a single string argument composed of it and subsequent quoted tokens:

# *Single* argument, because `a` is *unquoted*.
PS> Write-Output a' b '" c "
a b  c 

The same applies even if that first unquoted token is a (non-expression) variable reference (e.g., Write-Output $HOME/'folder 1'/"and more"; see this answer for more information


If you do need to reliably form a single string argument from a mix of double-quoted (interpolating) and single-quoted (verbatim) string literals, use (...), the grouping operator, and the + operator for explicit string concatenation:

PS> Write-Output (" a " + ' b ' + " c ")
 a  b  c 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...