代码之家  ›  专栏  ›  技术社区  ›  Alek Davis

为什么PowerShell不识别引用的参数?

  •  0
  • Alek Davis  · 技术社区  · 7 年前

    为什么在直接调用脚本(在PowerShell控制台或ISE中)或通过另一个PowerShell实例调用脚本时,PowerShell会以不同的方式处理引用的参数?

    这是剧本( TestQuotes.ps1 ):

    param
    (
        [string]
        $Config = $null
    )
    
    "Config = $Config"
    

    以下是结果:

    PS D:\Scripts> .\TestQuotes.ps1 -Config "A B C"
    Config = A B C
    PS D:\Scripts> PowerShell .\TestQuotes.ps1 -Config "A B C"
    Config = A
    PS D:\Scripts> .\TestQuotes.ps1 -Config 'A B C'
    Config = A B C
    PS D:\Scripts> PowerShell .\TestQuotes.ps1 -Config 'A B C'
    Config = A
    

    有什么想法吗?

    1 回复  |  直到 7 年前
        1
  •  7
  •   beatcracker    7 年前

    根据 PowerShell.exe Command-Line Help ,第一个论点 powershell 可执行文件是 -Command :

    PowerShell[.exe]
           [-Command { - | <script-block> [-args <arg-array>]
                         | <string> [<CommandParameters>] } ]
           [-EncodedCommand <Base64EncodedCommand>]
           [-ExecutionPolicy <ExecutionPolicy>]
           [-File <FilePath> [<Args>]]
           [-InputFormat {Text | XML}]
           [-Mta]
           [-NoExit]
           [-NoLogo]
           [-NonInteractive]
           [-NoProfile]
           [-OutputFormat {Text | XML}]
           [-PSConsoleFile <FilePath> | -Version <PowerShell version>]
           [-Sta]
           [-WindowStyle <style>]
    
    PowerShell[.exe] -Help | -? | /?
    

    之后有文本吗 -命令 作为单个命令行发送到PowerShell。

    ...

    -命令 是一根绳子, Command 必须是指定的最后一个参数,因为 在命令之后键入的任何字符都将被解释为命令参数 .

    PowerShell实例实际接收的子实例很容易检查 echoargs :

    PS > echoargs .\TestQuotes.ps1 -Config "A B C"
    Arg 0 is <.\TestQuotes.ps1>
    Arg 1 is <-Config>
    Arg 2 is <A B C>
    
    

    子实例进一步将其解析为:

    '.\TestQuotes.ps1' '-Config' 'A' 'B' 'C'
    

    这就是你得到“错误”结果的地方: Config = A

    如果你指定 -File 参数,您将得到所需的结果:

    PS >  PowerShell -File .\TestQuotes.ps1 -Config 'A B C'
    Config = A B C
    
    PS >  PowerShell -Command .\TestQuotes.ps1 -Config 'A B C'
    Config = A
    
        2
  •  5
  •   mklement0    7 年前

    tl;博士

    如果你是 调用另一个PowerShell实例 来自PowerShell ,使用 脚本块 ( { ... } ) 要获得可预测的行为:

    Windows PowerShell:

    powershell.exe { .\TestQuotes.ps1 -Config "A B C" }
    

    动力壳 果心 :

    pwsh { .\TestQuotes.ps1 -Config "A B C" }
    

    将使引用论点的工作如预期的那样 -它甚至还会回来 物体 由于采用了类似于PowerShell远程处理的序列化,因此调用具有接近类型保真度。

    然而,请注意,这是 从中呼叫时的选项 外部 动力地狱 ,例如 cmd.exe bash .

    请继续阅读,了解您在报告中看到的行为的解释 缺席 一个脚本块的。


    这个 PowerShell CLI (呼叫) powershell.exe (Windows PowerShell)/ pwsh.exe (PowerShell) 果心 ) 仅支持 参数,该参数接受 位置的 论点 (即,值前面没有 参数名 例如 -Command ).

    • 在里面 Windows PowerShell, 这个(隐含的)参数是 -命令 .

    • 在里面 动力壳 果心 是的 -File .

    有争论吗 之后 第一个位置参数(如果有)将被考虑:

    • 在Windows PowerShell中: PowerShell源代码片段的一部分 传递给(隐含的)
      -命令 参数

    • 在PowerShell中 果心 : 个人论点 作为文字传递 脚本文件 第一位置论元 (暗示) -文件 (论点)。


    传递给 -命令 -无论是隐式的还是显式的-经历 几轮解析 通过PowerShell,这可能很棘手:

    • 第一 圆的,圆的 "..." (双引号)包含单个参数的 脱光 .

      • 如果你打电话 来自PowerShell ,这甚至适用于 原来 '...' -封闭式(单引号),因为在幕后,PowerShell 重新引用 这样的论据可以使用 "..." 打电话的时候 外部程序 (包括PowerShell CLI本身)。
    • 第二 在这一轮中,被剥夺的论点是 加入空格 组成一个 单串 就是 然后 解释为 PowerShell源代码 .


    应用于你的调用,这意味着 二者都 PowerShell .\TestQuotes.ps1 -Config "A B C" PowerShell .\TestQuotes.ps1 -Config 'A B C' 最终导致PowerShell解析并执行以下代码:

    .\TestQuotes.ps1 -Config A B C
    

    就是, 由于进行了两轮分析,最初的引用是 迷路的 ,导致 不同的论点获得通过 ,这就解释了你的症状。


    如果必须的话 让你的命令发挥作用 没有 脚本块 ,你有两个选择:

    • 使用 -文件 哪一个 只适用于 一轮解析 :

      powershell.exe -File .\TestQuotes.ps1 -Config "A B C"
      
      • 就是, 除了剥去外壳 "..." ,得到的参数被视为 字面量 -然而,这是 典型的 你想要什么。
    • 有(暗示的) -命令 ,申请 额外的引用层 :

      powershell.exe -Command .\TestQuotes.ps1 -Config '\"A B C\"'
      

    请注意PowerShell是如何要求 " 查斯。作为逃犯 \" 在通过的辩论中 到它的CLI 鉴于 在PowerShell内部 , `" (或 "" )必须使用。

    推荐文章