顺便说一句:问题的引用相关部分可以通过在脚本路径中使用环境变量$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
为了能够将数组作为脚本文件参数传递,特别需要它;看到这个答案。
您的尝试的关键改进是:
笔记:
详情见下文。
另请注意,(进程)退出代码-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.exe
a 传递&
给正在调用的命令,它必须包含在 中"..."
,或者在这样的字符串之外,转义为^&
。
然而,即使解决一个问题是不够的:
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
如您所见,包含空格的脚本文件路径缺少必要的引用。
您有几个选项可以在脚本路径周围提供必要的引用:
如果您知道您的脚本路径不包含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"