Windows çıkış satırından uygulama çıkış kodunu nasıl alabilirim?


797

Bir program çalıştırıyorum ve (farklı hatalara dayalı farklı kodlar döndürdüğü için) dönüş kodunun ne olduğunu görmek istiyorum.

Bash’te bunu çalıştırarak biliyorum

echo $?

Windows'ta cmd.exe'yi kullanırken ne yapmalıyım?



1
Linux'ta yapabileceğimiz gibi "Win8 CMD'nin çıkış durumunu gösterme istemi nasıl alınır?" Bu üst seçim oldu ve doğrudur.
SDsolar

1
Hangi uygulamanın geri döndüğünü hızlı bir şekilde görebilirsiniz:app.exe & echo %errorlevel%
marbel82

Yanıtlar:


976

Adlı bir sözde ortam değişkeni errorlevelçıkış kodunu saklar:

echo Exit Code is %errorlevel%

Ayrıca, ifkomutun özel bir sözdizimi vardır:

if errorlevel

Ayrıntılar if /?için bakınız.

Misal

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

Uyarı: Bir ortam değişkeni adı verirseniz errorlevel, %errorlevel%bu değeri değil çıkış kodu döndürür. set errorlevel=Ortam değişkeni errorlevelaracılığıyla gerçek değerine erişime izin vererek, ortam değişkenini temizlemek için ( ) kullanın %errorlevel%.


38
Doğrudan bir Windows komut satırından çalıştırıyorsanız ve her zaman 0 döndürüldüğünü görüyorsanız, Gary'nin cevabına bakın: stackoverflow.com/a/11476681/31629
Ken

9
Ayrıca powershell iseniz kullanabilirsinizecho Exit Code is $LastExitCode
Brandon Pugh

11
Not: errorlevel> = 1 ise "errorlevel 1" doğrudur. Yani "errorlevel 0" her şeyle eşleşecektir. Eğer görürsen /?". Bunun yerine, "if% ERRORLEVEL% EQU 0 (..)" kullanabilirsiniz.
Curtis Yallop

1
%ERRORLEVEL%Bir hata oluşmasına rağmen 0 olan durumlar bulundu . %ERRORLEVEL%Bir cmd dosyasını kontrol ederken oldu . Denemek start /waitişe yaramadı. Çalışan tek şeyif errorlevel 1 (...)
AlikElzin-kilaka

1
Dostça tavsiye:% ErrorLevel%, bir ortam değişkeni değil, bir kabuk değişkendir ve aynı zamanda bir / stringdeğil int, etkin EQ/ kullanamayacağınız anlamına gelir NEQ.
kayleeFrye_onDeck

277

Test ErrorLevel, konsol uygulamaları için çalışır , ancak dmihailescu tarafından ima edildiği gibi , komut isteminden pencereli bir uygulamayı (örn. Win32 tabanlı) çalıştırmaya çalışıyorsanız bu çalışmaz . Pencereli bir uygulama arka planda çalışır ve kontrol hemen komut istemine döner ( ErrorLevelişlemin başarıyla oluşturulduğunu göstermek için büyük olasılıkla sıfır ile ). Pencereli bir uygulama sonunda çıktığında, çıkış durumu kaybolur.

Bununla birlikte, başka bir yerde bahsedilen konsol tabanlı C ++ başlatıcısını kullanmak yerine, komut isteminin komutunu kullanarak pencereli bir uygulamayı başlatmak daha basit bir alternatiftir START /WAIT. Bu, pencereli uygulamayı başlatır, çıkmasını bekler ve ardından ayarlanan işlemin çıkış durumuyla komutu komut istemine döndürür ErrorLevel.

start /wait something.exe
echo %errorlevel%

20
"BAŞLAT / Bekle" fikri için çok teşekkürler. Bu benim için çalıştı :)
Timotei

3
güzel yakalayış. O komutu bilmiyordum. Ben sadece bunun için çalışma gördüm> start / wait notepad.exe
dmihailescu

1
Çalışmamasının başka bir nedeni (her zaman sıfır) bir ifveya içinde olması for. !errorlevel!Bunun yerine, bu cevapta açıklandığı gibi kullanmayı düşünün .
Roman Starkov


23

Hata koduyla tam olarak eşleşmek istiyorsanız (örn. 0'a eşittir), bunu kullanın:

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

if errorlevel 0errorlevel= 0 ile eşleşir if /?. Bkz .


Büyük / küçük harfe duyarlı mı?
Nishant

1
Hayır. Vars, komutlar ("if" dahil) ve "equ" durum ne olursa olsun çalışır.
Curtis Yallop

14

Konsola bağlı olmayan bir program kullanılırken düzgün çalışmayabilir, çünkü siz çıkış koduna sahip olduğunuzu düşünürken bu uygulama hala çalışıyor olabilir. C ++ ile yapmak için bir çözüm aşağıdaki gibi görünüyor:

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

Bazı yapılandırmalarda CString türünün tanınması için #include <atlstr.h> eklemeniz gerekir.
Jake OPJ

8

.BAT ve .CMD dosyalarının farklı çalıştığını belirtmek gerekir.

Okuma https://ss64.com/nt/errorlevel.html o aşağıdakileri notları:

.CMD ve .BAT toplu iş dosyalarının hata düzeylerini ayarlama biçimi arasında önemli bir fark vardır:

'Yeni' dahili komutları çalıştıran eski bir .BAT toplu iş komut dosyası: APPEND, ASSOC, PATH, PROMPT, FTYPE ve SET yalnızca bir hata oluşursa ERRORLEVEL ayarlayacaktır. Toplu iş komut dosyasında iki komutunuz varsa ve ilk komut başarısız olursa, ERRORLEVEL ikinci komut başarılı olduktan sonra bile ayarlanmış olarak kalır.

Bu, bir hata ayıklama BAT komut dosyası daha zor hale getirebilir, bir CMD toplu komut dosyası daha tutarlıdır ve [kaynak] çalıştırdığınız her komuttan sonra ERRORLEVEL ayarlayacaktır.

Bu, ardışık komutları yürütürken bana kederin sonu vermiyordu, ancak bir hata durumunda ERRORLEVEL değişmeden kalacaktı.


0

Bir noktada, günlük olaylarını Cygwin'den Windows Olay günlüğüne doğru bir şekilde aktarmam gerekiyordu. WEVL'deki mesajların özel olmasını, doğru çıkış koduna, detaylara, önceliklere, mesajlara vb. Sahip olmasını istedim. Bu yüzden bununla ilgilenmek için küçük bir Bash betiği oluşturdum. İşte GitHub'da, logit.sh .

Bazı alıntılar:

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"

Geçici dosya içeriği kısmı:

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"

İşte WEVL'de etkinlik oluşturmak için bir işlev:

__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
}

Toplu komut dosyasını çalıştırma ve __create_event'i çağırma:

cmd /c "$(cygpath -wa "$LGT_TEMP_FILE")"
__create_event
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.