【发布时间】:2021-04-06 20:13:51
【问题描述】:
我怀疑没有好的解决方案,但也许我忽略了一些东西:
我追求的是一种方法:
-
(a) 从 PowerShell 调用批处理文件的方式稳健地 反映其在 PowerShell 的自动
$LASTEXITCODE变量中的隐式或显式退出代码。-
值得注意的是,调用以
whoami -nosuch || exit /b退出的批处理文件应该导致$LASTEXITCODE反映whoami的退出代码,即1。当您从 PowerShell 调用批处理文件(按名称或路径)时,情况不是:退出代码是0(相比之下,在cmd.exe会话中%ERRORLEVEL%是设置为1)。 -
另外请注意,调用应该与 PowerShell 的输出流保持集成,所以我不在寻找基于
System.Diagnostics.Process的解决方案。 -
此外,我不了解或控制被调用的批处理文件 - 我正在寻找一个通用的解决方案。
-
-
(b) 传递给批处理文件的双引号参数不会以任何方式被更改,并且
cmd.exe的行为不会以任何方式被修改;特别是:-
^字符不应加倍(见下文)。 - 使用
/V:ON启用延迟扩展 是不是一个选项。
-
我知道如何解决 (a) 的唯一方法是通过 cmd /c call 调用批处理文件。
不幸的是,这违反了要求 (b),因为在参数中使用 call 似乎总是将 ^ 字符加倍。 (相反,not 使用 call 不会可靠地报告退出代码。
有没有办法同时满足两个的要求?
请注意,PowerShell 只是这里的信使:问题在于cmd.exe,任何从cmd.exe 会话之外调用批处理文件的人都面临同样的问题。
示例(PowerShell 代码):
# Create a (temporary) batch file that echoes its arguments,
# provokes an error, and exits with `exit /b` *without an explicit argument*.
'@echo off & echo [%*] & whoami -nosuch 2>NUL || exit /b' | Set-Content test.cmd
# Invoke the batch file and report the exit code.
.\test.cmd "a ^ 2"; $LASTEXITCODE
输出应该是:
["a ^ 2"]
1
然而,实际上退出代码是不报告的:
["a ^ 2"]
0 # !! BROKEN
如果我改为使用cmd /c call .\test.cmd 调用,则退出代码是正确的,但^ 字符会加倍:
PS> cmd /c call .\test.cmd "a ^ 2"; $LASTEXITCODE
["a ^^ 2"] # !! BROKEN
1 # OK
【问题讨论】:
-
这对我有用:
cmd '/c .\test.cmd "a ^ 2" & exit /b'。它会从您的测试批处理文件中返回正确的输出,如果我把乱码放在那里,我会在$LASTEXITCODE(MSG_DIR_BAD_COMMAND_OR_FILE) 中得到9009。 -
太好了,@beatcracker - 请将其发布为答案,我会接受。我试过
|| exit /b,它应该工作;尝试& exit /b我什至没有想到 - 它表明cmd.exe本身并不知道批处理文件失败,但不知何故确实通过exit /b传递了它的非零退出代码。 ????♂️ -
你提到
%ERRORLEVEL% is set to 1给了我一个提示,这样的东西可能起作用;)。
标签: powershell batch-file cmd parameter-passing exit-code