teclado que linea consola con como comandos codigo basicos avanzados abrir windows command-line process cmd exit-code

que - ¿Cómo obtengo el código de salida de la aplicación desde una línea de comando de Windows?



linea de comandos windows (7)

Estoy ejecutando un programa y quiero ver cuál es su código de retorno (ya que devuelve códigos diferentes en función de diferentes errores).

Sé que en Bash puedo hacer esto corriendo

echo $?

¿Qué hago cuando uso cmd.exe en Windows?


En un momento necesario, tuve que enviar con precisión los eventos de registro de Cygwin al registro de eventos de Windows. Quería que los mensajes en WEVL fueran personalizados, que tuvieran el código de salida correcto, los detalles, las prioridades, el mensaje, etc. Así que creé un pequeño script de Bash para encargarme de esto. Aquí está en GitHub, logit.sh .

Algunos extractos:

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"

Aquí está la parte del contenido del archivo temporal:

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"

Aquí hay una función para crear eventos en 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 }

Ejecutando el script por lotes y llamando a __create_event:

cmd /c "$(cygpath -wa "$LGT_TEMP_FILE")" __create_event


Es posible que no funcione correctamente cuando se utiliza un programa que no está conectado a la consola, ya que la aplicación podría seguir funcionando mientras creas que tienes el código de salida. Una solución para hacerlo en C ++ se ve a continuación:

#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; }


Las pruebas ErrorLevel funcionan para las aplicaciones de consola , pero como indica dmihailescu , esto no funcionará si está intentando ejecutar una aplicación de ventana (por ejemplo, basada en Win32) desde un indicador de comandos. Una aplicación con ventanas se ejecutará en segundo plano, y el control volverá inmediatamente al símbolo del sistema (lo más probable es que con un ErrorLevel de cero para indicar que el proceso se creó correctamente). Cuando una aplicación de ventana finalmente sale, su estado de salida se pierde.

Sin embargo, en lugar de usar el iniciador de C ++ basado en consola mencionado en otra parte, una alternativa más simple es iniciar una aplicación de ventana utilizando el comando START /WAIT del símbolo del sistema. Esto iniciará la aplicación de ventana, esperará a que salga y, a continuación, devolverá el control al símbolo del sistema con el estado de salida del proceso establecido en ErrorLevel .

start /wait something.exe echo %errorlevel%


Si desea hacer coincidir exactamente el código de error (por ejemplo, es igual a 0), use esto:

@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 coincide con errorlevel > = 0. ¿Ver if /? .



Vale la pena señalar que los archivos .BAT y .CMD funcionan de manera diferente.

Al leer https://ss64.com/nt/errorlevel.html se observa lo siguiente:

Hay una diferencia clave entre la forma en que los archivos de proceso por lotes .CMD y .BAT establecen los niveles de error:

Un antiguo script por lotes .BAT que ejecuta los ''nuevos'' comandos internos: APPEND, ASSOC, PATH, PROMPT, FTYPE y SET solo establecerá ERRORLEVEL si se produce un error. Por lo tanto, si tiene dos comandos en el script por lotes y el primero falla, ERRORLEVEL permanecerá configurado incluso después de que el segundo comando tenga éxito.

Esto puede hacer que la depuración de un script BAT problemático sea más difícil, un script por lotes de CMD es más consistente y establecerá ERRORLEVEL después de cada comando que ejecute [source].

Esto me estaba causando un sinfín de dolores, ya que estaba ejecutando comandos sucesivos, pero ERRORLEVEL permanecería sin cambios incluso en el caso de una falla.


Una variable de pseudo entorno llamada errorlevel almacena el código de salida:

echo Exit Code is %errorlevel%

Además, el comando if tiene una sintaxis especial:

if errorlevel

Ver if /? para detalles.

Ejemplo

@echo off my_nify_exe.exe if errorlevel 1 ( echo Failure Reason Given is %errorlevel% exit /b %errorlevel% )

Advertencia: si establece un nombre de variable de entorno errorlevel , %errorlevel% devolverá ese valor y no el código de salida. Utilice (set errorlevel= ) para borrar la variable de entorno, permitiendo el acceso al valor verdadero de errorlevel través de la variable de entorno %errorlevel% .