[英]How do I get the application exit code from a Windows command line?
我正在運行一個程序並想查看它的返回代碼是什么(因為它根據不同的錯誤返回不同的代碼)。
我知道在 Bash 中我可以通過運行來做到這一點
回聲 $?
在 Windows 上使用 cmd.exe 時該怎么辦?
一個名為errorlevel
偽環境變量存儲退出代碼:
echo Exit Code is %errorlevel%
此外, if
命令有一個特殊的語法:
if errorlevel
看看if /?
詳情。
@echo off
my_nify_exe.exe
if errorlevel 1 (
echo Failure Reason Given is %errorlevel%
exit /b %errorlevel%
)
警告:如果您設置環境變量名稱errorlevel
, %errorlevel%
將返回該值而不是退出代碼。 使用 ( set errorlevel=
) 清除環境變量,允許通過%errorlevel%
環境變量訪問errorlevel
的真實值。
測試ErrorLevel
適用於控制台應用程序,但正如dmihailescu所暗示的那樣,如果您嘗試從命令提示符運行窗口應用程序(例如基於 Win32 的應用程序),這將不起作用。 窗口化應用程序將在后台運行,並且控制權將立即返回到命令提示符(最有可能的ErrorLevel
為零表示該進程已成功創建)。 當窗口化應用程序最終退出時,其退出狀態將丟失。
不過,與使用其他地方提到的基於控制台的 C++ 啟動器不同,更簡單的替代方法是使用命令提示符的START /WAIT
命令啟動窗口應用程序。 這將啟動窗口化應用程序,等待它退出,然后將控制權返回到命令提示符,並在ErrorLevel
中設置進程的退出狀態。
start /wait something.exe
echo %errorlevel%
如果要精確匹配錯誤代碼(例如等於 0),請使用以下命令:
@echo off
my_nify_exe.exe
if %ERRORLEVEL% EQU 0 (
echo Success
) else (
echo Failure Reason Given is %errorlevel%
exit /b %errorlevel%
)
if errorlevel 0
匹配錯誤errorlevel
>= 0。看看if /?
.
使用未附加到控制台的程序時,它可能無法正常工作,因為當您認為擁有退出代碼時,該應用程序可能仍在運行。 在 C++ 中執行此操作的解決方案如下所示:
#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'\n",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....\n", 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)\n", GetLastError() );
return GetLastError();
}
else
printf( "Waiting for \"%ws\" to exit.....\n", strCmd );
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
int result = -1;
if(!GetExitCodeProcess(pi.hProcess,(LPDWORD)&result))
{
printf("GetExitCodeProcess() failed (%d)\n", GetLastError() );
}
else
printf("The exit code for '%ws' is %d\n",(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它注意到以下內容:
.CMD 和 .BAT 批處理文件設置錯誤級別的方式有一個關鍵區別:
運行“新”內部命令的舊 .BAT 批處理腳本:APPEND、ASSOC、PATH、PROMPT、FTYPE 和 SET 僅在發生錯誤時設置 ERRORLEVEL。 因此,如果批處理腳本中有兩個命令並且第一個失敗,則即使第二個命令成功,ERRORLEVEL 仍將保持設置。
這會使調試有問題的 BAT 腳本更加困難,CMD 批處理腳本更加一致,並且會在您運行每個命令后設置 ERRORLEVEL [source]。
這讓我在執行連續命令時悲痛不已,但即使發生故障,ERRORLEVEL 也將保持不變。
有一次我需要准確地將日志事件從 Cygwin 推送到 Windows 事件日志。 我希望 WEVL 中的消息是自定義的,具有正確的退出代碼、詳細信息、優先級、消息等。所以我創建了一個小 Bash 腳本來處理這個問題。 這是在 GitHub 上的logit.sh 。
部分摘錄:
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"
這是臨時文件內容部分:
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 中創建事件的函數:
__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:
cmd /c "$(cygpath -wa "$LGT_TEMP_FILE")"
__create_event
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.