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.exe
a&
传递给正在调用的命令,它必须包含在 中"..."
,或者在该字符串之外转义为^&
。
然而,即使解决一个问题还不够:
rem # !! Still doesn't work
powershell ^& "C:\Program Files\Folder\file.ps1 -verbose:$True -restart"
Run Code Online (Sandbox Code Playgroud)
另一个问题是,当您使用-Command
CLI 参数(在您的情况中隐含)时,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 次 |
最近记录: |