首页 > 解决方案 > 使用命令行中的完整路径和参数运行 powershell 命令

问题描述

我有一个位于Program Files文件夹中并接受参数的脚本: 从其文件夹中运行它可以完美运行verboserestart

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

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

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

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

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

我错过了什么?

标签: powershellcommand-linecommand-prompt

解决方案


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


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

但是,当使用PowerShell 的 CLI时,使用( ) 来执行脚本会更简单-File-f,这样就&不需要并简化了引用:

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

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

仅当您需要传递一段 PowerShell 代码和/或参数时才使用-Command( )必须像从PowerShell内部-c那样解释脚本文件参数:

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

注意:-Command为了能够将数组作为脚本文件参数传递,特别需要它;看到这个答案

您的尝试的关键改进是:

  • &被放置在里面"...",这样可以防止PowerShell 看到它之前自行cmd.exe解释它。

  • 脚本路径包含在嵌入的引号 ( '...') 中,以便 PowerShell 将路径视为引号。

笔记:

  • -Command用于清楚起见;在Windows PowerShell中,它可以被省略(就像你所做的那样),因为它是默认参数;但是请注意,在 PowerShell Core中,默认值为 now -File。有关两个 PowerShell CLI 的全面概述,请参阅此答案

  • 您并不严格需要将所有内容都作为一个 "..."字符串传递,但这种方式在概念上更清晰。

详情见下文。

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


至于你尝试了什么:

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

这意味着您是从cmd.exe(从命令提示符或批处理文件)调用的,其中&包含的"..."具有特殊含义:它是命令序列运算符。

也就是说,您的命令相当于以下2 个命令,按顺序执行:

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

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

请注意,您的具体症状表明您只使用"C:\Program Files\Folder\<file.ps1>"了第二个命令,没有参数,它确实会将该脚本文件作为文档打开,以进行编辑

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

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

然而,即使解决一个问题是不够的:

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

另一个问题是,当您使用-CommandCLI 参数时, PowerShell使用以下逻辑来处理参数:

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

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

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

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

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


如果您知道您的脚本路径不包含chars '请使用嵌入式 '...'引用:

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

仅使用一对外部"字符,您不必担心在参数到达PowerShell之前cmd.exe无意中预先解释了参数。

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

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

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

Windows PowerShell中,您可以通过使用"^""(sic) 来避免这种情况,但请注意,在 PowerShell Core中,您将获得与使用\"".

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"

推荐阅读