tl;dr
REM From cmd.exe (Command Prompt) / a batch file:
powershell.exe -c Start-Process cmd.exe -Verb RunAs ('/k {0} \"a\" \"B C\" \"d\"' -f ((Convert-Path 'TestEnv.cmd') -replace ' ', '^^ '))
如果你还想确保批处理文件在调用者的当前目录中执行:
REM From cmd.exe (Command Prompt) / a batch file:
powershell.exe -c Start-Process cmd.exe -Verb RunAs ('/k cd \"{0}\" ^&^& {1} \"a\" \"B C\" \"d\"' -f $PWD.ProviderPath, ((Convert-Path 'TestEnv.cmd') -replace ' ', '^^ '))
继续阅读以获得解释。
主要问题是:
-
当您将批处理文件路径直接 - 作为可执行文件 - 传递给Start-Process -Verb RunAs 时,传递包含双引号的参数列表似乎存在问题 (@987654333 @) - 我不知道原因,但问题出现在下面 PowerShell 的层中,可能在底层System.Diagnostics.ProcessStartInfo .NET API 中,甚至可能在底层@987654322 中@WinAPI 函数。
-
(如果你需要 no 参数或者它们都不需要",你可以直接将批处理文件路径作为可执行文件传递;默认情况下,因为底层可执行文件是cmd.exe,它位于C:\Windows\System32,C:\Windows\System32 成为工作目录,您可以使用-WorkingDirectory 覆盖它,但请注意,您必须使用(可能是相对的)引用批处理文件路径,如果它位于其他地方。)
解决方法:
-
不要使用批处理文件路径直接作为要启动的可执行文件,而是使用cmd.exe作为可执行文件,并将批处理文件路径及其所有参数作为参数传递给@987654342 @ 选项(或 /k,如果您想保持新窗口打开)。
-
不幸的是,-Verb Runas、cmd.exe 总是使用 C:\Windows\System32 作为新进程的工作目录 - 传递带有 -WorkingDirectory 参数的启动目录然后被忽略。
- 这同样适用于
powershell.exe,但奇怪的是,不适用于pwsh.exe(PowerShell [Core] v6+)和基于.NET的可执行文件,它们( a) 默认保留调用者的工作目录,并且 (b) 遵守 -WorkingDirectory 参数。
-
因此,如果您的 TestEnv.cmd 批处理文件位于 当前 目录中 - 而不是 PATH 环境变量 ($env:PATH) 中列出的目录 - 您必须通过批处理文件的完整路径到cmd.exe,您可以使用Convert-Path 确定。
从 PowerShell 内部 这意味着您的命令必须如下所示(请注意,我使用 /k 保持新窗口打开,用于诊断目的;使用/c 在批处理文件退出时自动关闭窗口):
# From inside PowerShell:
Start-Process cmd.exe -Verb RunAs (
'/k {0} "a" "B C" "d"' -f ((Convert-Path 'TestEnv.cmd') -replace ' ', '^ ')
)
警告:由于正在调用cmd.exe,因此C:\Windows\System32 是工作目录。
如果您还想确保批处理文件在调用者的当前目录中执行,则必须在前面添加cd 命令:
# From inside PowerShell:
Start-Process cmd.exe -Verb RunAs (
'/k cd "{0}" && {1} "a" "B C" "d"' -f $PWD.ProviderPath, ((Convert-Path 'TestEnv.cmd') -replace ' ', '^ ')
)
从cmd.exe(命令提示符)/批处理文件、通过Windows PowerShell's CLI、powershell.exe(请注意,在PowerShell [Core ] v6+ 现在是pwsh),增加了额外的复杂性:
REM From cmd.exe (Command Prompt) / a batch file:
powershell.exe -c Start-Process cmd.exe -Verb RunAs ('/k {0} \"a\" \"B C\" \"d\"' -f ((Convert-Path 'TestEnv.cmd') -replace ' ', '^^ '))
如果你还想确保批处理文件在调用者的当前目录中执行:
REM From cmd.exe (Command Prompt) / a batch file:
powershell.exe -c Start-Process cmd.exe -Verb RunAs ('/k cd \"{0}\" ^&^& {1} \"a\" \"B C\" \"d\"' -f $PWD.ProviderPath, ((Convert-Path 'TestEnv.cmd') -replace ' ', '^^ '))