Pseudo zmienna środowiskowa o nazwie errorlevelprzechowuje kod wyjścia:
echo Exit Code is %errorlevel%
Ponadto ifpolecenie ma specjalną składnię:
if errorlevel
Zobacz if /?szczegóły.
Przykład
@echo off
my_nify_exe.exe
if errorlevel 1 (
echo Failure Reason Given is %errorlevel%
exit /b %errorlevel%
)
Ostrzeżenie: jeśli ustawisz nazwę zmiennej środowiskowej errorlevel, %errorlevel%zwróci tę wartość, a nie kod wyjścia. Użyj ( set errorlevel=), aby wyczyścić zmienną środowiskową, umożliwiając dostęp do prawdziwej wartości za errorlevelpośrednictwem %errorlevel%zmiennej środowiskowej.
Uwaga: „poziom błędu 1” jest prawdziwy, jeśli poziom błędu> = 1. Zatem „poziom błędu 0” będzie pasował do wszystkiego. Zobacz „if /?”. Zamiast tego możesz użyć „jeśli% ERRORLEVEL% EQU 0 (..)”.
Znaleziono przypadki, w których %ERRORLEVEL%wynosi 0, mimo że wystąpił błąd. Zdarzyło się podczas %ERRORLEVEL%wpisywania pliku cmd. Próbowanie start /waitnie zadziałało. Jedyne, co zadziałało, toif errorlevel 1 (...)
Przyjazna rada:% ErrorLevel% jest zmienną powłoki, a nie zmienną środowiskową, a także zwraca wartość stringan int, co oznacza, że nie można używać EQ/ NEQskutecznie.
Testowanie ErrorLeveldziała dla aplikacji konsolowych , ale jak sugeruje dmihailescu , nie zadziała to, jeśli próbujesz uruchomić aplikację okienkową (np. Opartą na Win32) z wiersza poleceń. Aplikacja działająca w oknie uruchomi się w tle, a kontrola natychmiast powróci do wiersza poleceń (najprawdopodobniej z ErrorLevelzerą wskazującą, że proces został pomyślnie utworzony ). Gdy aplikacja okienkowa ostatecznie kończy działanie, jej status wyjścia zostaje utracony.
Zamiast korzystać z konsolowego programu uruchamiającego C ++ wspomnianego w innym miejscu, prostszą alternatywą jest uruchomienie aplikacji okienkowej za pomocą polecenia wiersza START /WAITpolecenia. Spowoduje to uruchomienie aplikacji okienkowej, poczekanie na jej zakończenie, a następnie przywrócenie sterowania do wiersza polecenia ze statusem zakończenia procesu ustawionym w ErrorLevel.
Innym powodem, dla którego może nie działać (zawsze zero) jest to, że znajduje się w iflub for. Rozważ użycie !errorlevel!zamiast tego, jak opisano w tej odpowiedzi .
Może nie działać poprawnie, gdy używasz programu, który nie jest podłączony do konsoli, ponieważ ta aplikacja może nadal działać, gdy uważasz, że masz kod wyjścia. Rozwiązanie w C ++ wygląda następująco:
#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 FALSE0,// 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());returnGetLastError();}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;}
Istnieje zasadnicza różnica między sposobem ustawiania poziomów błędów w plikach wsadowych .CMD i .BAT:
Stary skrypt wsadowy .BAT uruchamiający „nowe” komendy wewnętrzne: APPEND, ASSOC, PATH, PROMPT, FTYPE i SET ustawią ERRORLEVEL tylko w przypadku wystąpienia błędu. Więc jeśli masz dwa polecenia w skrypcie wsadowym, a pierwsze nie powiedzie się, ERRORLEVEL pozostanie ustawiony nawet po udanym drugim poleceniu.
Może to utrudnić debugowanie skryptu BAT, skrypt wsadowy CMD jest bardziej spójny i ustawi ERRORLEVEL po każdej komendzie, którą uruchomisz [źródło].
Nie powodowało to końca smutku, gdy wykonywałem kolejne polecenia, ale ERRORLEVEL pozostałby niezmieniony nawet w przypadku awarii.
W pewnym momencie musiałem dokładnie przesłać zdarzenia dziennika z Cygwin do dziennika zdarzeń Windows. Chciałem, aby komunikaty w WEVL były niestandardowe, miały poprawny kod wyjścia, szczegóły, priorytety, komunikat itp. Więc stworzyłem mały skrypt Bash, aby się tym zająć. Tutaj jest na GitHub, logit.sh .
Niektóre fragmenty:
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"
Oto część zawartości pliku tymczasowego:
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"
Oto funkcja tworzenia zdarzeń w 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
}
Wykonanie skryptu wsadowego i wywołanie __create_event:
Używamy plików cookie i innych technologii śledzenia w celu poprawy komfortu przeglądania naszej witryny, aby wyświetlać spersonalizowane treści i ukierunkowane reklamy, analizować ruch w naszej witrynie, i zrozumieć, skąd pochodzą nasi goście.
Kontynuując, wyrażasz zgodę na korzystanie z plików cookie i innych technologii śledzenia oraz potwierdzasz, że masz co najmniej 16 lat lub zgodę rodzica lub opiekuna.