【问题标题】:Running a powershell command using full path and arguments from command line [duplicate]使用命令行的完整路径和参数运行powershell命令[重复]
【发布时间】:2019-08-10 09:51:54
【问题描述】:

我有一个位于 Program Files 文件夹中并接受参数的脚本:verboserestart 从其文件夹中运行它非常有效:

powershell ./<file.ps1> -verbose:$True -restart

尝试使用完整路径运行它是我遇到问题的地方:

powershell & "C:\Program Files\Folder\<file.ps1> -verbose:$True -restart"

上面的命令不运行脚本;相反,它打开 PS 命令提示符,退出它时,它会在记事本中打开脚本。
我还尝试将每个变量放在单独的引号中,但效果不佳。

我通过使用 progra~1 而不是 Program Files 找到了解决方法,但我想以正确的方式解决问题。

我错过了什么?

【问题讨论】:

    标签: powershell command-line command-prompt


    【解决方案1】:

    顺便说一句:通过在脚本路径中使用环境变量 $env:ProgramFiles 而不是文字 "C:\Program Files\..." 可以避免问题的引用相关部分,这会将命令简化为:
    powershell "&amp; $env:ProgramFiles\Folder\file.ps1 -verbose:$True -restart"


    确实,为了在 PowerShell 中执行由带有嵌入空格的文字路径引用的脚本,这些路径必须被 引用,并且引用的路径必须是 传递给&amp;.

    但是,当使用PowerShell's CLI 时,使用-File (-f) 来执行脚本会更简单,这使得&amp; 变得不必要并简化了引用:

    powershell -File "C:\Program Files\Folder\file.ps1" -Verbose -Restart
    

    从外部调用 PowerShell 时-File 后面的参数被字面意思(删除语法 "..." 后,如果present) - 如果您从 inside PowerShell 运行命令,它们的解释方式;例如,当从 外部 PowerShell 调用时,powershell -File script.ps1 $env:USERNAME 会将字符串 $env:USERNAME 逐字 传递给 script.ps1 而不是扩展它 - 如果你需要,使用-Command

    仅当您需要传递 PowerShell 代码的 sn-p 和/或参数时,才使用 -Command (-c) 和/或参数 必须像从内部 PowerShell

    powershell -Command "& 'C:\Program Files\Folder\file.ps1' -Verbose:$true -Restart"
    

    注意:特别需要-Command 才能将数组 作为脚本文件参数传递;见this answer

    您的尝试的关键改进是:

    • &amp; 被放置在"..." 中,这可以防止cmd.exe 解释它本身PowerShell 看到它之前。

    • 脚本路径包含在 嵌入 引用 ('...') 中,因此 PowerShell 将路径视为引用。

    注意:

    • -Command 用于清楚起见;在 Windows PowerShell 中,它可以被省略(就像你所做的那样),因为它是 default 参数;但是请注意,在 PowerShell Core 中,默认值现在是 -File。请参阅this answer 以全面了解这两个 PowerShell CLI。

    • 您不需要将所有内容都作为 one "..." 字符串传递,但这样在概念上更清晰。

    详情见下文。

    另请注意,(进程)退出代码的设置方式在 -File-Command 之间有所不同 - 请参阅 this answer


    至于你尝试了什么

    上面的命令不运行脚本;相反,它打开 PS 命令提示符,退出它时,它会在记事本中打开脚本。

    这意味着您是从cmd.exe(从命令提示符或批处理文件)调用的,其中&amp; 未包含在"..." 中具有特殊含义:它是 command-sequencing 操作符。

    也就是说,你的命令相当于下面的2个命令,依次执行

    powershell
    "C:\Program Files\Folder\file.ps1 -verbose:$True -restart"
    

    第一个命令打开一个 交互式 PowerShell 会话。 只有在您手动退出后,才会执行第二个命令。

    请注意,您的具体症状表明您只使用了"C:\Program Files\Folder\&lt;file.ps1&gt;",不带参数,作为第二个命令,它确实会将该脚本文件作为文档打开,用于编辑 em>。

    使用参数,整个双引号字符串被解释为文件名,你会得到通常的... is not recognized as an internal or external command, operable program or batch file.

    为了cmd.exe&amp; 通过 传递给正在调用的命令,它必须包含在"..." 中,或者在这样的字符串之外,转义为^&amp;

    但是,即使解决一个问题还不够:

    rem # !! Still doesn't work
    powershell ^& "C:\Program Files\Folder\file.ps1 -verbose:$True -restart"
    

    另一个问题是,当您使用-Command CLI 参数时,在您的情况下隐含,PowerShell 使用以下逻辑来处理参数:

    • 每个参数都被剥离了其封闭的"..."(如果存在)。
    • 剥离的参数与空格连接。
    • 生成的单个字符串然后作为 PowerShell 代码执行。

    也就是说,使用上面的命令 PowerShell 尝试执行具有以下逐字内容的字符串:

    & C:\Program Files\Folder\file.ps1 -verbose:$True -restart
    

    如您所见,包含空格的脚本文件路径缺少必要的引用。

    您有几个选项可以在脚本路径周围提供必要的引用:


    如果您知道您的脚本路径包含' 字符,请使用嵌入 '...' 引用:

    powershell -Command "& 'C:\Program Files\Folder\file.ps1' -Verbose:$true -Restart"
    

    只有一对外部的" 字符。您不必担心cmd.exe 会在参数到达PowerShell 之前预先解释

    也可以在这种情况下省略外部引用,但这会使 未引用 参数容易受到cmd.exe 不必要的解释(尽管在这种情况下很好) ,并注意'cmd.exe 中没有特殊含义,因此cmd.exe 将PowerShell 样式的'...' 字符串视为未引用

    rem # Works, but generally less robust than the above.
    powershell -Command ^& 'C:\Program Files\Folder\file.ps1' -Verbose:$true -Restart
    

    如果您想确保包含嵌入 ' 字符的偶数路径。正常工作

    使用嵌入的引用," 转义为\"(原文如此):

    powershell -Command "& \"C:\Program Files\Folder\file.ps1\" -Verbose:$true -Restart"
    

    不幸的是,这再次使\" 实例之间的字符串受到cmd.exe 潜在有害解释的影响。

    您可以改用\""(原文如此)来解决此问题,但这会使\"" 实例之间的字符串受到空白规范化:也就是说,一行中的多个空格是折叠成一个。

    Windows PowerShell 中,您可以通过使用 "^""(原文如此)来避免这种情况,但请注意,在 PowerShell Core 中,您将获得与使用 @ 相同的行为987654387@.

    rem # The most robust form in Windows PowerShell.
    rem # Still subject to whitespace normalization in PowerShell Core.
    powershell -Command "& "^""C:\Program Files\Folder\file.ps1"^"" -Verbose:$true -Restart"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-15
      • 2020-12-30
      • 2023-04-06
      • 2013-03-24
      • 2018-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多