Bagaimana cara mendapatkan kode keluar aplikasi dari baris perintah Windows?

797

Saya menjalankan suatu program dan ingin melihat apa kode pengembaliannya (karena ia mengembalikan kode yang berbeda berdasarkan kesalahan yang berbeda).

Saya tahu di Bash saya bisa melakukan ini dengan berlari

echo $?

Apa yang saya lakukan ketika menggunakan cmd.exe di Windows?

Skrud
sumber
1
Di-Google-kan untuk "Win8 Cara mendapatkan CMD prompt untuk menunjukkan status keluar" seperti yang bisa kita lakukan di Linux. Ini adalah pilihan teratas, dan akurat.
SDsolar
1
Anda dapat dengan cepat melihat aplikasi yang dikembalikan:app.exe & echo %errorlevel%
marbel82

Jawaban:

976

Variabel lingkungan pseudo bernama errorlevelmenyimpan kode keluar:

echo Exit Code is %errorlevel%

Juga, ifperintah memiliki sintaks khusus:

if errorlevel

Lihat if /?detailnya.

Contoh

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

Peringatan: Jika Anda menetapkan nama variabel lingkungan errorlevel, %errorlevel%akan mengembalikan nilai itu dan bukan kode keluar. Gunakan ( set errorlevel=) untuk menghapus variabel lingkungan, memungkinkan akses ke nilai sebenarnya errorlevelmelalui %errorlevel%variabel lingkungan.

DrFloyd5
sumber
38
Jika Anda menjalankan langsung dari baris perintah Windows dan selalu melihat 0 dikembalikan, lihat jawaban Gary: stackoverflow.com/a/11476681/31629
Ken
9
Juga jika Anda menggunakan PowerShell, Anda dapat menggunakanecho Exit Code is $LastExitCode
Brandon Pugh
11
Catatan: "errorlevel 1" benar jika errorlevel> = 1. Jadi "errorlevel 0" akan cocok dengan segalanya. Lihat jika /?". Sebagai gantinya, Anda dapat menggunakan "jika% ERRORLEVEL% EQU 0 (..)".
Curtis Yallop
1
Ditemukan kasus di mana %ERRORLEVEL%0 meskipun terjadi kesalahan. Terjadi ketika memeriksa %ERRORLEVEL%dalam file cmd. Berusaha start /waittidak berhasil. Satu-satunya hal yang berhasil adalahif errorlevel 1 (...)
AlikElzin-kilaka
1
Saran ramah:% ErrorLevel% adalah variabel shell, bukan variabel lingkungan, dan juga mengembalikan stringbukan int, yang berarti Anda tidak dapat menggunakan EQ/ NEQsecara efektif.
kayleeFrye_onDeck
277

Pengujian ErrorLevelberfungsi untuk aplikasi konsol , tetapi seperti yang disarankan oleh dmihailescu , ini tidak akan berfungsi jika Anda mencoba menjalankan aplikasi berjendela (misalnya berbasis Win32) dari prompt perintah. Aplikasi berjendela akan berjalan di latar belakang, dan kontrol akan segera kembali ke command prompt (kemungkinan besar dengan ErrorLevelnol untuk menunjukkan bahwa proses telah berhasil dibuat ). Ketika aplikasi berjendela akhirnya keluar, status keluarnya hilang.

Alih-alih menggunakan peluncur C ++ berbasis konsol yang disebutkan di tempat lain, alternatif yang lebih sederhana adalah memulai aplikasi berjendela menggunakan perintah command prompt START /WAIT. Ini akan memulai aplikasi berjendela, menunggu aplikasi keluar, dan kemudian kembali kontrol ke prompt perintah dengan status keluar dari proses yang ditetapkan ErrorLevel.

start /wait something.exe
echo %errorlevel%
Gary
sumber
20
Terima kasih banyak untuk ide "MULAI / tunggu". Itu berhasil bagi saya :)
Timotei
3
tangkapan bagus. Saya tidak tahu tentang perintah itu. Saya baru saja melihatnya berfungsi untuk> mulai / tunggu notepad.exe
dmihailescu
1
Alasan lain mengapa itu mungkin tidak berhasil (selalu nol) adalah ketika itu di dalam ifatau for. Pertimbangkan menggunakan !errorlevel!sebagai gantinya, seperti yang dijelaskan dalam jawaban ini .
Roman Starkov
23

Jika Anda ingin mencocokkan kode kesalahan dengan tepat (mis. Sama dengan 0), gunakan ini:

@echo off
my_nify_exe.exe
if %ERRORLEVEL% EQU 0 (
   echo Success
) else (
   echo Failure Reason Given is %errorlevel%
   exit /b %errorlevel%
)

if errorlevel 0pertandingan errorlevel> = 0. Lihat if /?.

Curtis Yallop
sumber
Apakah ini case-sensitive?
Nishant
1
Tidak. Vars, perintah (termasuk "jika") dan "equ" berfungsi tidak masalah apa masalahnya.
Curtis Yallop
14

Mungkin tidak berfungsi dengan benar ketika menggunakan program yang tidak terpasang ke konsol, karena aplikasi itu mungkin masih berjalan saat Anda berpikir Anda memiliki kode keluar. Solusi untuk melakukannya di C ++ terlihat seperti di bawah ini:

#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;
}
dmihailescu
sumber
Dalam beberapa konfigurasi Anda harus menambahkan #include <atlstr.h> sehingga tipe CString direkondisi.
Jake OPJ
8

Perlu dicatat bahwa file .BAT dan .CMD beroperasi secara berbeda.

Membaca https://ss64.com/nt/errorlevel.html mencatat hal-hal berikut:

Ada perbedaan utama antara cara .CMD dan .BAT file batch mengatur tingkat kesalahan:

Skrip batch .BAT tua yang menjalankan perintah internal 'baru': APPEND, ASSOC, PATH, PROMPT, FTYPE, dan SET hanya akan mengatur ERRORLEVEL jika terjadi kesalahan. Jadi jika Anda memiliki dua perintah dalam skrip batch dan yang pertama gagal, ERRORLEVEL akan tetap disetel bahkan setelah perintah kedua berhasil.

Ini dapat membuat debug masalah skrip BAT lebih sulit, skrip batch CMD lebih konsisten dan akan mengatur ERRORLEVEL setelah setiap perintah yang Anda jalankan [sumber].

Ini membuat saya tidak berduka karena saya mengeksekusi perintah yang berurutan, tetapi ERRORLEVEL akan tetap tidak berubah bahkan jika terjadi kegagalan.

RockDoctor
sumber
0

Pada satu titik, saya perlu mendorong peristiwa log secara akurat dari Cygwin ke Windows Event log. Saya ingin pesan dalam WEVL menjadi khusus, memiliki kode keluar yang benar, detail, prioritas, pesan, dll. Jadi saya membuat skrip Bash kecil untuk menangani hal ini. Ini dia di GitHub, logit.sh .

Beberapa kutipan:

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"

Inilah bagian isi file sementara:

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"

Berikut adalah fungsi untuk membuat acara di 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
}

Menjalankan skrip batch dan memanggil __create_event:

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