提问人:StrangerDanger 提问时间:11/18/2023 最后编辑:mklement0StrangerDanger 更新时间:11/18/2023 访问量:66
从批处理文件或命令行打开我的 PowerShell 脚本时,它不起作用,但在直接运行时可以工作
My PowerShell script does not work when opening it from a batch file or the command line, but it works when running directly
问:
我正在尝试做什么:
使用 .bat 文件调用生成自签名证书和密钥对 (.pem) 的 .ps1 文件(不要询问),然后 .bat 文件会将每个 .pem 移动到新目录。
我做了什么:
我有 .ps1 文件正常工作,它生成两个文件,但它确实需要以管理员身份运行 PowerShell。我有 .bat 文件在应该调用 .ps1 文件时调用。在批处理文件中,我正在打开 PowerShell,然后以管理员身份打开另一个 PowerShell 实例(因为无法从命令行以管理员身份运行 PS,如果我错了,请纠正我)。下面是代码行:
PowerShell -Command "& {Start-Process PowerShell -ArgumentList '-NoExit -File ""cert-gen.ps1""' -Verb RunAs}"
发生了什么事情:
运行此行时,我看到弹出一个 PS 窗口并立即关闭,它不会生成我的证书和密钥。由于它立即关闭,我看不到该窗口中是否有任何错误,并且命令行确实显示任何错误。我很确定我在正确的地方。-NoExit
奖金:
这需要完全自动化,无需用户交互,因此 UAC 提升的提示将不起作用。我最终也需要找到解决这个问题的方法,所以如果有一个解决方案可以一次性解决所有这些问题,那就更好了!
答:
:: From a batch file
PowerShell -Command "Start-Process PowerShell -ArgumentList '-NoExit -File \"%CD%\cert-gen.ps1\"' -Verb RunAs"
主要问题是,当使用提升调用
powershell.exe
(Windows PowerShell CLI)时,它总是使用C:\Windows\System32
作为工作目录。因此,它无法在那里找到您的脚本。cert-gen.ps1
%CD%\cert-gen.ps1
确保脚本通过其完整路径传递,从而解决该问题。 按 up front 展开,到当前目录的完整路径。%CD%
cmd.exe
请注意,您的脚本必须准备好处理作为工作目录运行的问题;例如,如果需要,它可以使用自动
$PSScriptRoot
变量来引用自己的目录。C:\Windows\System32
顺便说一句:不幸的是,如果找不到目标脚本,则通过调用的 CLI 会话会自动关闭(当与失败的命令一起使用时,会话保持打开状态);GitHub 问题 #10471 建议更改此行为。
-NoExit
-File
-Command
移除了不必要的外壳:
& { ... }
- 没有理由使用通过 () 参数传递给 PowerShell 的 CLI 的代码 - 直接使用即可。旧版本的 CLI 文档错误地建议这是必需的,但此后已得到纠正。
"& { ... }"
-Command
-c
"..."
& { ... }
- 没有理由使用通过 () 参数传递给 PowerShell 的 CLI 的代码 - 直接使用即可。旧版本的 CLI 文档错误地建议这是必需的,但此后已得到纠正。
虽然转义嵌入的字符恰好在这种情况下起作用,但它不能稳健地工作,所以改用:
""
"
\"
至于问题的UAC部分:
防止批处理文件触发 UAC 提示的唯一安全方法是从已提升的会话运行它 - 但请注意,启动此类会话本身将触发 UAC 提示。
因此,如果确保批处理文件作为一个整体以提升方式运行(如果并非其中的所有操作实际上都需要提升,这本身可能被视为安全风险),则可以简化对 PowerShell CLI 的调用(如果只是为了进行故障排除,请考虑将其删除):
-NoExit
PowerShell -NoExit -File cert-gen.ps1
也就是说,直接调用是可能的,因为从提升的进程启动的子进程也会被提升。
本答案讨论了不安全的替代方案。
评论
CMD.exe
PowerShell.exe
PowerShell.exe
PowerShell -File "cert-gen.ps1"