使用命令行中的完整路径和参数运行 powershell 命令

ocp*_*000 8 powershell command-line command-prompt

我有一个位于Program Files文件夹中并接受参数的脚本:verbose从其restart 文件夹运行它效果很好:

powershell ./<file.ps1> -verbose:$True -restart
Run Code Online (Sandbox Code Playgroud)

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

powershell & "C:\Program Files\Folder\<file.ps1> -verbose:$True -restart"
Run Code Online (Sandbox Code Playgroud)

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

我找到了使用progra~1代替的解决方法Program Files,但我想以正确的方式解决问题。

我缺少什么?

mkl*_*nt0 10

顺便说一句:问题的引用相关部分可以通过使用环境变量$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
Run Code Online (Sandbox Code Playgroud)

当从外部调用 PowerShell 时,后面的参数按字面-File意思获取(删除语法后"...",如果存在的话) - 它们不会像从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"
Run Code Online (Sandbox Code Playgroud)

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

您的尝试的关键改进是:

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

  • 脚本路径包含在嵌入式引号 ( '...') 中,以便 PowerShell 看到带引号的路径。

笔记:

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

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

详情请参阅下文。

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


至于你尝试过的

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

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

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

powershell
"C:\Program Files\Folder\file.ps1 -verbose:$True -restart"
Run Code Online (Sandbox Code Playgroud)

第一个命令打开交互式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"
Run Code Online (Sandbox Code Playgroud)

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

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

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

& C:\Program Files\Folder\file.ps1 -verbose:$True -restart
Run Code Online (Sandbox Code Playgroud)

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

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


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

powershell -Command "& 'C:\Program Files\Folder\file.ps1' -Verbose:$true -Restart"
Run Code Online (Sandbox Code Playgroud)

由于只有一对外部字符",您不必担心在参数到达 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
Run Code Online (Sandbox Code Playgroud)

如果你想确保即使是带有嵌入'字符的路径。好好工作

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

powershell -Command "& \"C:\Program Files\Folder\file.ps1\" -Verbose:$true -Restart"
Run Code Online (Sandbox Code Playgroud)

不幸的是,这再次使实例之间的字符串\"受到可能不需要的解释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"
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

28273 次

最近记录:

1 年,11 月 前