How do I get the application exit code from a Windows command line?
我正在运行一个程序,想看看它的返回代码是什么(因为它根据不同的错误返回不同的代码)。
我知道在Bash中我可以通过运行来做到这一点
echo $?
在Windows上使用cmd.exe时该怎么办?
名为
1 | echo Exit Code is %errorlevel% |
此外,
1 | if errorlevel |
有关详细信息,请参阅
例
1 2 3 4 5 6 | @echo off my_nify_exe.exe if errorlevel 1 ( echo Failure Reason Given is %errorlevel% exit /b %errorlevel% ) |
警告:如果设置环境变量名称
测试
但是,更简单的替代方法是使用命令提示符的
1 2 | start /wait something.exe echo %errorlevel% |
使用内置的ERRORLEVEL变量:
1 | echo %ERRORLEVEL% |
但要注意应用程序是否定义了名为ERRORLEVEL的环境变量!
如果要精确匹配错误代码(例如等于0),请使用:
1 2 3 4 5 6 7 8 | @echo off my_nify_exe.exe if %ERRORLEVEL% EQU 0 ( echo Success ) else ( echo Failure Reason Given is %errorlevel% exit /b %errorlevel% ) |
使用未附加到控制台的程序时,它可能无法正常工作,因为当您认为有退出代码时,该应用程序可能仍在运行。
用C ++实现它的解决方案如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | #include"stdafx.h" #include"windows.h" #include"stdio.h" #include"tchar.h" #include"stdio.h" #include"shellapi.h" int _tmain( int argc, TCHAR *argv[] ) { CString cmdline(GetCommandLineW()); cmdline.TrimLeft('"'); CString self(argv[0]); self.Trim('"'); CString args = cmdline.Mid(self.GetLength()+1); args.TrimLeft(_T(""")); printf("Arguments passed: '%ws' ",args); STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); if( argc < 2 ) { printf("Usage: %s arg1,arg2.... ", argv[0]); return -1; } CString strCmd(args); // Start the child process. if( !CreateProcess( NULL, // No module name (use command line) (LPTSTR)(strCmd.GetString()), // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE 0, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi ) // Pointer to PROCESS_INFORMATION structure ) { printf("CreateProcess failed (%d) ", GetLastError() ); return GetLastError(); } else printf("Waiting for "%ws" to exit..... ", strCmd ); // Wait until child process exits. WaitForSingleObject( pi.hProcess, INFINITE ); int result = -1; if(!GetExitCodeProcess(pi.hProcess,(LPDWORD)&result)) { printf("GetExitCodeProcess() failed (%d) ", GetLastError() ); } else printf("The exit code for '%ws' is %d ",(LPTSTR)(strCmd.GetString()), result ); // Close process and thread handles. CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); return result; } |
值得注意的是.BAT和.CMD文件的运行方式不同。
阅读https://ss64.com/nt/errorlevel.html,它注意到以下内容:
There is a key difference between the way .CMD and .BAT batch files set errorlevels:
An old .BAT batch script running the 'new' internal commands: APPEND, ASSOC, PATH, PROMPT, FTYPE and SET will only set ERRORLEVEL if an error occurs. So if you have two commands in the batch script and the first fails, the ERRORLEVEL will remain set even after the second command succeeds.
This can make debugging a problem BAT script more difficult, a CMD batch script is more consistent and will set ERRORLEVEL after every command that you run .
这导致我在执行连续命令时没有悲伤,但即使发生故障,ERRORLEVEL也会保持不变。
有一次,我需要准确地将日志事件从Cygwin推送到Windows事件日志。我希望WEVL中的消息是自定义的,具有正确的退出代码,详细信息,优先级,消息等。所以我创建了一个小的Bash脚本来处理这个问题。这是在GitHub上,logit.sh。
一些摘录:
1 2 | usage: logit.sh [-h] [-p] [-i=n] [-s] <description> example: logit.sh -p error -i 501 -s myscript.sh"failed to run the mount command" |
这是临时文件内容部分:
1 2 3 4 5 6 7 | LGT_TEMP_FILE="$(mktemp --suffix .cmd)" cat<<EOF>$LGT_TEMP_FILE @echo off set LGT_EXITCODE="$LGT_ID" exit /b %LGT_ID% EOF unix2dos"$LGT_TEMP_FILE" |
这是在WEVL中创建事件的功能:
1 2 3 4 5 6 7 8 9 10 11 | __create_event () { local cmd="eventcreate /ID $LGT_ID /L Application /SO $LGT_SOURCE /T $LGT_PRIORITY /D" if [["$1" == *';'* ]]; then local IFS=';' for i in"$1"; do $cmd"$i" &>/dev/null done else $cmd"$LGT_DESC" &>/dev/null fi } |
执行批处理脚本并调用__create_event:
1 2 | cmd /c"$(cygpath -wa"$LGT_TEMP_FILE")" __create_event |