顺便说一句:通过在脚本路径中使用环境变量 $env:ProgramFiles 而不是文字 "C:\Program Files\..." 可以避免问题的引用相关部分,这会将命令简化为:
powershell "& $env:ProgramFiles\Folder\file.ps1 -verbose:$True -restart"
确实,为了在 PowerShell 中执行由带有嵌入空格的文字路径引用的脚本,这些路径必须被 引用,并且引用的路径必须是 传递给&或.
但是,当使用PowerShell's CLI 时,使用-File (-f) 来执行脚本会更简单,这使得& 变得不必要并简化了引用:
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。
您的尝试的关键改进是:
注意:
详情见下文。
另请注意,(进程)退出代码的设置方式在 -File 和 -Command 之间有所不同 - 请参阅 this answer。
至于你尝试了什么:
上面的命令不运行脚本;相反,它打开 PS 命令提示符,退出它时,它会在记事本中打开脚本。
这意味着您是从cmd.exe(从命令提示符或批处理文件)调用的,其中& 未包含在"..." 中具有特殊含义:它是 command-sequencing 操作符。
也就是说,你的命令相当于下面的2个命令,依次执行:
powershell
"C:\Program Files\Folder\file.ps1 -verbose:$True -restart"
第一个命令打开一个 交互式 PowerShell 会话。
只有在您手动退出后,才会执行第二个命令。
请注意,您的具体症状表明您只使用了"C:\Program Files\Folder\<file.ps1>",不带参数,作为第二个命令,它确实会将该脚本文件作为文档打开,用于编辑 em>。
使用参数,整个双引号字符串被解释为文件名,你会得到通常的... is not recognized as an internal or external command, operable program or batch file.
为了cmd.exe 将& 通过 传递给正在调用的命令,它必须包含在"..." 中,或者在这样的字符串之外,转义为^&。
但是,即使解决一个问题还不够:
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"