问题描述
我在尝试运行此代码时遇到以下错误,但不知道如何解决。任何想法?
$Chocopackage = "packagename"
$localprograms = choco list --localonly
start-process -Wait -FilePath "C:\ProgramData\chocolatey\choco.exe" -ArgumentList "install $Chocopackage -ia "'/D=C:\Program Files\packagename'" -y"
start-process : A positional parameter cannot be found that accepts argument '/D=C:\Program Files\packagename'.
At C:\Program Files\install.ps1:3 char:5
+ start-process -Wait -FilePath "C:\ProgramData\chocolatey\choco.ex ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [start-process],ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.StartProcessCommand
解决方法
注意:
- 正如您在自己的回答中指出的那样,special quoting requirements 适用于
cocho.exe
的/ia
参数。 - 但是,由于您使用的是
Start-Process
,不是PowerShell 链接页面中的说明适用于这种情况,但是cmd.exe
的那些(尽管此调用中没有 shell;但是,像cmd.exe
一样,控制台应用程序本身通常只理解 {{1} } 引用);也就是说,您的"..."
字符串必须以包含以下 verbatim 结尾,这就是传递给下面-ArgumentList
的字符串通过嵌入的-ArgumentList
字符转义为 { {1}}("
也可以):`"
""
仅当您从 PowerShell 直接调用 "/D=""C:\Program Files\packagename"""
时,PowerShell 说明才适用 (Start-Process -Wait -FilePath "C:\ProgramData\chocolatey\choco.exe" `
-ArgumentList "install $ChocoPackage -ia `"/D=`"`"C:\Program Files\packagename`"`"`" -y"
):
choco.exe
至于你尝试了什么:
您传递给 '/D=""C:\Program Files\packagename""'
的内容由 三个 以 & "C:\ProgramData\chocolatey\choco.exe" install $ChocoPackage -ia '/D=""C:\Program Files\packagename""' -y
形式直接相邻的字符串文字组成,使用一个简化的示例(即双引号右在单引号字符串旁边,在另一个双引号字符串旁边)。
但是,PowerShell 不完全支持隐式直接连接字符串文字的串联以形成单个参数,就像与 POSIX 兼容的 shell(例如 {{1} } 做;这样做会导致字符串作为 separate 参数传递,这导致了您的问题(-ArgumentList
在 " a "' b '" c "
之后看到了它没想到的额外位置参数)。
使用简化示例演示原始问题:
bash
也就是说,Start-Process
接收字符串文字 -ArgumentList
、PS> Write-Output " a "' b '" c "
a
b
c
和 Write-Output
作为 3 个单独的参数(正如它们各自出现在自己的行中所暗示的那样)。
仅当第一个标记未加引号时,您才会得到一个单个字符串参数,由它和后续标记组成引用标记:
" a "
即使第一个未加引号的标记是(非表达式)变量引用(例如,' b '
;有关详细信息,请参阅 this answer),同样适用
如果您确实需要从双引号(插值)和单引号(逐字)字符串文字的混合中可靠地形成单个字符串参数,请使用 " c "
、grouping operator 和 # *Single* argument,because `a` is *unquoted*.
PS> Write-Output a' b '" c "
a b c
运算符用于显式字符串连接:
Write-Output $HOME/'folder 1'/"and more"
,
哦,当然,我在阅读了 Chocolatey 官方文档后几乎立即就明白了。由于我使用的是 powershell,因此您必须非常具体地将空格括在引号中。
-ia '/yo=""Spaces spaces""'
https://docs.chocolatey.org/en-us/choco/commands/#how-to-pass-options-switches
在参数中传递引号:当您需要将带引号的值传递给诸如本机安装程序之类的东西时,您将进入一个有趣的世界。在 cmd.exe 中,您必须像这样传递它:-ia "/yo=""Spaces space"""。在 PowerShell.exe 中,您必须像这样传递它:-ia '/yo=""Spaces space""'。没有其他组合将起作用。在 PowerShell.exe 中,如果您使用的是 v3+ 版本,则可以在 -ia 之前尝试 --% 以按原样传递参数,这意味着它不需要任何特殊的解决方法。