Comment puis-je obtenir le code de sortie de L'application à partir d'une ligne de commande Windows?
j'exécute un programme et je veux voir quel est son code de retour (puisqu'il renvoie des codes différents basés sur des erreurs différentes).
je sais en Bash, je peux le faire en cours d'exécution
echo $?
7 réponses
une variable d'environnement pseudo nommée errorlevel
stocke le code de sortie:
echo Exit Code is %errorlevel%
aussi, la commande if
a une syntaxe spéciale:
if errorlevel
voir if /?
pour plus de détails.
exemple
@echo off
my_nify_exe.exe
if errorlevel 1 (
echo Failure Reason Given is %errorlevel%
exit /b %errorlevel%
)
Avertissement: Si vous définissez un nom de variable d'environnement errorlevel
, %errorlevel%
permet de retourner la valeur et non le code de sortie. Utilisation (set errorlevel=
) pour effacer la variable d'environnement, permettant l'accès à la vraie valeur de errorlevel
via le %errorlevel%
variable d'environnement.
Test ErrorLevel
travaille pour console applications, mais aussi de faire allusion à une par dmihailescu , cela ne fonctionnera pas si vous essayez d'exécuter un fenêtré de l'application (par exemple, Win32) à partir d'une invite de commande. Une application fenêtrée s'exécute en arrière-plan, et le contrôle retourne immédiatement à l'invite de commande (très probablement avec un ErrorLevel
de zéro pour indiquer que le processus a été créé avec succès). Quand une application fenêtrée sort finalement, son statut de sortie est perdu.
au lieu d'utiliser le lanceur C++ basé sur la console mentionné ailleurs, cependant, une alternative plus simple est de démarrer une application fenêtrée en utilisant la commande START /WAIT
de l'invite de commande. Cela va lancer la fenêtre de l'application, attendre pour sortir, puis revenir à l'invite de commandes avec le code de sortie du processus défini dans ErrorLevel
.
start /wait something.exe
echo %errorlevel%
utilisez la Variable ERRORLEVEL intégrée:
echo %ERRORLEVEL%
mais attention si une application a défini une variable d'environnement appelée ERRORLEVEL !
cela pourrait ne pas fonctionner correctement en utilisant un programme qui n'est pas attaché à la console, parce que cette application pourrait toujours être en cours d'exécution alors que vous pensez avoir le code de sortie. Une solution pour le faire en C++ ressemble à ceci:
#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;
}
si vous voulez faire correspondre exactement le code d'erreur (eg égale 0), utilisez ceci:
@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
correspond à errorlevel
>= 0. Voir if /?
.
à un moment, j'ai eu besoin de pousser avec précision les événements de journal de Cygwin au Journal D'événements de Windows. Je voulais que les messages dans WEVL soient personnalisés, aient le code de sortie correct, les détails, les priorités, le message, etc. Alors j'ai créé un petit script Bash pour m'occuper de ça. Le voici sur GitHub, logit.sh .
quelques extraits:
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"
Voici la partie du contenu du fichier temporaire:
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"
ici est une fonction pour créer des événements dans WEVL:
__create_event () {
local cmd="eventcreate /ID $LGT_ID /L Application /SO $LGT_SOURCE /T $LGT_PRIORITY /D "
if [[ "" == *';'* ]]; then
local IFS=';'
for i in ""; do
$cmd "$i" &>/dev/null
done
else
$cmd "$LGT_DESC" &>/dev/null
fi
}
exécution du script de lot et appel à _ _ create _ event:
cmd /c "$(cygpath -wa "$LGT_TEMP_FILE")"
__create_event
il est intéressant de noter que .Chauve-souris et .Les fichiers CMD fonctionnent différemment.
Lire https://ss64.com/nt/errorlevel.html il note ce qui suit:
il y a une différence clé entre le chemin .CMD and .Les fichiers batch mis errorlevels:
Un vieux .Le script BAT-bat qui exécute les' nouvelles ' commandes internes: ajoute, ASSOC, PATH, PROMPT, FTYPE et SET ne définira ERRORLEVEL que si un erreur se produit. Ainsi, si vous avez deux commandes dans le script batch et que la première échoue, le niveau D'erreur restera défini même après que la seconde commande ait réussi.
cela peut rendre le débogage d'un script BAT plus difficile, un script cmd batch est plus cohérent et définira ERRORLEVEL après chaque commande que vous lancerez [source].
cela ne me causait aucune fin de chagrin car j'exécutais des commandes successives, mais le niveau D'erreur serait restent inchangés même en cas de panne.