【问题标题】:Powershell "A positional parameter cannot be found that accepts argument"Powershell“找不到接受参数的位置参数”
【发布时间】:2021-02-10 19:52:59
【问题描述】:

我在尝试运行此代码时遇到以下错误,我不确定如何解决它。有什么想法吗?

$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

【问题讨论】:

    标签: powershell chocolatey


    【解决方案1】:

    注意:

    • 正如您在自己的回答中指出的那样,special quoting requirements 适用于choco.exe/ia 参数。
    • 但是,由于您使用的是Start-Process,因此不是在这种情况下适用的PowerShell链接页面中的说明,而是那些对于cmd.exe(即使在此调用中没有 shell;但是,与cmd.exe 一样,控制台应用程序本身通常只能理解"..." 引用);也就是说,您的-ArgumentList 字符串最终必须包含以下逐字,这就是传递给下面-ArgumentList 的字符串通过嵌入的" 字符转义为`" (""也可以):
      "/D=""C:\Program Files\packagename"""
    Start-Process -Wait -FilePath "C:\ProgramData\chocolatey\choco.exe" `
      -ArgumentList "install $ChocoPackage -ia `"/D=`"`"C:\Program Files\packagename`"`"`" -y"
    

    仅当您从 PowerShell 直接 调用 choco.exe 时,PowerShell 指令才会适用 ('/D=""C:\Program Files\packagename""'):

    & "C:\ProgramData\chocolatey\choco.exe" install $ChocoPackage -ia '/D=""C:\Program Files\packagename""' -y
    

    至于你尝试了什么

    您传递给 -ArgumentList 的内容由 三个 直接相邻的字符串文字组成,格式为 " a "' b '" c ",使用一个简化的示例(即,单引号旁边的双引号字符串)带引号的字符串,紧挨着另一个双引号字符串)。

    但是,PowerShell 不完全支持 隐式 连接直接相邻的字符串文字以形成单个参数,就像 bash 等 POSIX 兼容的 shell 所做的那样;这样做会导致字符串作为单独的参数传递,这会导致您的问题(Start-Process-ArgumentList 之后看到了额外的位置参数,这是意料之外的)。

    用简化示例演示原始问题:

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

    也就是说,Write-Output 将字符串文字 " a "' b '" c " 作为 3 个单独的参数接收(正如它们各自出现在自己的行中所暗示的那样)。

    只有当 first 标记是unquoted 你会得到一个 single 字符串参数 由它和后续引用标记:

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

    即使第一个不带引号的标记是(非表达式)变量引用(例如,Write-Output $HOME/'folder 1'/"and more";有关更多信息,请参阅this answer


    如果您确实需要从双引号(插值)和单引号(逐字)字符串文字的混合中可靠地形成单个字符串参数,请使用 (...) strong>、grouping operator+ 运算符用于显式字符串连接

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

    【讨论】:

    • 哇,这就是完整答案的样子。谢谢。
    • 以你的解释能力,你需要写一本书——我的拙见。
    【解决方案2】:

    当然,在阅读了 Chocolatey 官方文档后,我几乎立刻就明白了。由于我使用的是 powershell,因此您必须非常具体地使用引号将空格括起来。

    -ia '/yo=""Spaces spaces""'
    

    https://docs.chocolatey.org/en-us/choco/commands/#how-to-pass-options-switches

    在参数中传递引号:当您需要将带引号的值传递给诸如本机安装程序之类的东西时,您将进入一个有趣的世界。在 cmd.exe 中,您必须像这样传递它:-ia "/yo=""Spaces spaces"""。在 PowerShell.exe 中,您必须像这样传递它:-ia '/yo=""Spaces spaces""'。没有其他组合将起作用。在 PowerShell.exe 中,如果您使用的是 v3+ 版本,则可以在 -ia 之前尝试 --% 以按原样传递参数,这意味着它不需要任何特殊的解决方法。

    【讨论】:

    • 很好地找到了特殊的引用要求,但请注意,不是适用于您的情况的 PowerShell 指令,而是适用于 cmd.exe 的指令(在某种意义上由于使用Start-Process,您必须仅使用"..." 引用);详情请看我的回答。
    猜你喜欢
    • 2015-05-21
    • 2017-11-06
    • 2016-05-27
    • 1970-01-01
    • 2019-05-07
    • 2016-07-06
    • 2014-09-30
    相关资源
    最近更新 更多