Як отримати код виходу програми з командного рядка Windows?


797

Я запускаю програму і хочу побачити, який її код повернення (оскільки він повертає різні коди на основі різних помилок).

Я знаю, що в Bash я можу це зробити, бігаючи

ехо $?

Що робити під час використання cmd.exe для Windows?



1
Google для "Win8 Як отримати підказку CMD, щоб показати статус виходу", як ми можемо зробити в Linux. Це був найкращий вибір, і це точно.
SDsolar

1
Ви можете швидко побачити, що додаток повертається:app.exe & echo %errorlevel%
marbel82

Відповіді:


976

Змінна псевдосередовища з назвою 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%змінну оточення.


38
Якщо ви працюєте безпосередньо з командного рядка Windows і завжди бачите 0 повернених, дивіться відповідь Гері: stackoverflow.com/a/11476681/31629
Кен

9
Також якщо ви перебуваєте в повному складі, то можете скористатисяecho Exit Code is $LastExitCode
Брендон П'ю

11
Примітка: "errorlevel 1" вірно, якщо errorlevel> = 1. Отже, "errorlevel 0" відповідатиме всім. Дивіться "якщо /?". Натомість ви можете використовувати "if% ERRORLEVEL% EQU 0 (..)".
Кертіс Яллоп

1
Знайдено випадки, коли %ERRORLEVEL%0, навіть якщо сталася помилка. Сталося під час перевірки %ERRORLEVEL%у cmd-файлі. Спроба start /waitне спрацювала. Єдине, що працювалоif errorlevel 1 (...)
АлікЕльзін-кілака

1
Дружні поради:% ErrorLevel% - це змінна оболонка, а не змінна середовище; вона також повертає значення " stringне" int, тобто ви не можете використовувати EQ/ NEQефективно.
kayleeFrye_onDeck

277

Тестування ErrorLevelпрацює для консольних програм, але, як натякнув dmihailescu , це не спрацює, якщо ви намагаєтеся запустити віконний додаток (наприклад, на основі Win32) з командного рядка. Віконна програма буде працювати у фоновому режимі, а керування негайно повернеться до командного рядка (швидше за все, з ErrorLevelнулем, щоб вказати, що процес створений успішно). Коли врезультатно закрита програма закривається, її статус виходу втрачається.

Замість використання консольного C ++-пускового пристрою, згаданого в іншому місці, однак, більш простою альтернативою є запуск віконної програми за допомогою команди командного рядка START /WAIT. Це запустить віконну програму, зачекає її виходу, а потім поверне управління до командного рядка зі статусом виходу процесу, встановленого в ErrorLevel.

start /wait something.exe
echo %errorlevel%

20
Велике спасибі за ідею "СТАРТ / чекай". Це працювало для мене :)
Тимотей

3
приємний улов. Я не знав про цю команду. Я щойно бачив, як це працює для> start / wait notepad.exe
dmihailescu

1
Ще одна причина, чому вона може не працювати (завжди дорівнює нулю), - це коли вона знаходиться всередині ifабо for. Розглянемо !errorlevel!натомість використання , як описано у цій відповіді .
Роман Старков

100

Використовуйте вбудовану змінну ERRORLEVEL:

echo %ERRORLEVEL%

Але будьте обережні, якщо програма визначила змінну середовища з назвою ERRORLEVEL !


6
Це не фактична змінна оточення (що, очевидно, чому вона перестає працювати , якщо є змінна з ім'ям , що шлях).
Joey

17
@SteelBrain: Це називається $LastExitCodeв PowerShell.
Олексій А.

23

Якщо ви хочете точно відповідати коду помилки (наприклад, дорівнює 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 /?.


Це залежно від регістру?
Нішант

1
Ні. Vars, команди (включаючи "if") та "equ" працюють, незалежно від випадку.
Кертіс Яллоп

14

Можливо, він не працює належним чином при використанні програми, не прикріпленої до консолі, тому що ця програма все ще може працювати, поки ви думаєте, що у вас є вихідний код. Рішення зробити це на 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;
}

У деяких конфігураціях слід додати #include <atlstr.h>, щоб тип CString був повторно розпізнаний.
Джейк OPJ

8

Варто зазначити, що файли .BAT і .CMD працюють по-різному.

Читаючи https://ss64.com/nt/errorlevel.html, вона зазначає наступне:

Існує ключова різниця між способом .CMD і .BAT-пакетних файлів, що встановлюють рівні помилок:

Старий пакетний скрипт .BAT, який виконує внутрішні команди 'new': APPEND, ASSOC, PATH, PROMPT, FTYPE і SET, встановить ERRORLEVEL лише у випадку помилки. Отже, якщо у пакетного скрипту у вас є дві команди, і перша не вдалася, ERRORLEVEL залишиться встановленою навіть після успіху другої команди.

Це може ускладнити налагодження проблемного BAT-скрипту, пакетний сценарій CMD є більш послідовним і встановить ERRORLEVEL після кожної команди, яку ви запускаєте [source].

Це не викликало у мене скорботи, коли я виконував послідовні команди, але ERRORLEVEL залишився незмінним навіть у разі відмови.


0

Якось мені потрібно було точно пересувати події журналу з 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.