使用 "cmd" 和 "start" 命令获取应用程序的退出代码

Getting the exit code of an application started with the "cmd" and "start" commands

我有一个控制台应用程序。与此应用程序的交互是通过 TCP/IP 完成的。

我也有一个测试框架,它基本上是 BATCH 脚本的集合(...不是我的错)。这个测试框架对每个测试所做的基本上是这样的:

  1. start /min "myapplication.exe" 并等待,直到收到应用程序已启动和 运行ning 的验证。
  2. 通过 TCP/IP 向此应用程序发送命令,接收其回复,并检查时间和值是否与特定测试预期的一致。

我目前遇到的一个问题是应用程序由于某些内部错误而过早退出。我想区分失败的测试和应用程序崩溃。我对此唯一的指示是应用程序的退出代码。

所以,我尝试了以下方法:

start /min cmd /c "myapplication.exe || echo %errorLevel% > exitcode.txt"

然后在测试脚本中,

if exist exitcode.txt (
    set /p exitcode=<exitcode.txt
    echo ERROR: myapplication.exe returned exitcode %exitcode%.
    goto error
) else (
    goto do_processing
)

但由于某些奇怪的原因,文本文件从未出现过,即使我有时会收到有关应用程序崩溃的对话框,即使我用已知的非零退出代码强行使其失败。测试刚刚通过 do_processing 并且(当然)导致失败。

编辑 当我 运行

start /min cmd /c "nonsense || echo %errorLevel% > test.txt"

有时 得到一个包含字符串 9009 的文本文件,但有时该文本文件包含字符串 0,或者有时 1,。 ..什么...?!

EDIT2 如果您键入

cmd /k "nonsense || echo %errorLevel%"

(注意 /k 选项),您会看到 0 被打印在新的 window 中,但是如果您随后键入 echo %errorlevel%,则会得到 1...

我知道批处理不是很正常,但至少应该一直很正常...

对这里可能发生的事情有什么想法吗?

here 所述,您必须使用 call 而不是 start 才能评估退出代码。 call 将在相同的变量环境中启动脚本,而 start 将 运行 在一个无法从第一个脚本访问的新环境中启动它。

%errorLevel%这样的正常扩展发生在语句解析的时候,一次解析整个CMD /C命令行,所以你得到的值是命令之前存在的值运行(始终为 0)。

您可以在 获得更准确的解释。一开始可能很难理解和理解这些阶段的意义,但值得付出努力。

要解决您的问题,您必须延迟变量的扩展,直到您的 exe 具有 运行.

您有两个选择:

选项 1) 使用 CALL 获得延迟一轮的扩展。

在批处理文件中,您可以将百分比加倍。但是使用 CMD /C 的命令 运行 是在命令行上下文下的 运行,而不是批处理。将百分比加倍在命令行下不起作用。

相反,您必须在变量名中引入插入符号(cmd.exe 转义符)。扩展的第一阶段发生在处理转义符之前,因此它会查找带有插入符号的名称,但没有找到。当找不到时,命令行解析器会在找不到变量时保留原始文本。接下来处理特殊字符并使用转义符。所以当 CALL 循环扩展发生时,它看到了正确的变量名。

start /min cmd /c "myapplication.exe || call echo %^errorLevel% > exitcode.txt"

我相信您是在批处理脚本中发出 START 命令,因此您还必须将百分比加倍以防止父批处理脚本扩展 ERRORLEVEL。

start /min cmd /c "myapplication.exe || call echo %%^errorLevel%% > exitcode.txt"

选项 2) 使用延迟扩展

延迟扩展语法是 !errorlevel! 而不是 %errorlevel%。但在使用之前,必须启用延迟扩展。在批处理脚本中,您可以使用 setlocal enableDelayedExpansion,但这在命令行上下文中不起作用。相反,您必须使用 cmd.exe /v:on 选项。

假设您的批处理脚本没有启用延迟扩展,那么您只需使用以下内容:

start /min cmd /v:on /c "myapplication.exe || echo !errorLevel! > exitcode.txt"

但是如果您的批处理脚本启用了延迟扩展,那么您必须转义 ! 以便父批处理脚本不会扩展 ERRORLEVEL。请注意,您仍必须使用 /v:on,因为 STARTed 子流程(通常)默认禁用延迟扩展。

start /min cmd /v:on /c "myapplication.exe || echo ^!errorLevel^! > exitcode.txt"

另一个解决方案可能是使用 & 而不是 ||

start myapplication.exe ^& echo %errorLevel% ^> exitcode.txt

^ 是一个转义字符,因此它是在开始内部而不是外部进行计算的 here

这对我有用。希望对大家有帮助。