web-gelistirme-sc.com

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

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

Bash'de çalıştırarak bunu yapabildiğimi biliyorum

eko mu?

Cmd.exe dosyasını Windows'ta kullanırken ne yapabilirim?

708
Skrud

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

echo Exit Code is %errorlevel%

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

if errorlevel

Ayrıntılar için if /? bölümüne bakın.

Örnek

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

Uyarı: errorlevel bir ortam değişkeni adı belirlerseniz, %errorlevel% çıkış kodunu değil bu değeri döndürür. Ortam değişkenini temizlemek için (set errorlevel=) kullanın, %errorlevel% ortam değişkeni ile errorlevel öğesinin gerçek değerine erişime izin verin.

863
Samuel Renkert

ErrorLevel sınaması console uygulamaları için çalışır, ancak ile dmihailescu ile gösterildiği gibi, eğer bir windowed application (ör. Win32 tabanlı) çalıştırmaya çalışıyorsanız, işe yaramaz ) bir komut isteminden. Pencereli bir uygulama arka planda çalışacak ve kontrol hemen Prompt komutuna geri dönecektir (büyük olasılıkla işlemin create başarıyla olduğunu belirtmek için sıfırın ErrorLevel si ile). Pencereli bir uygulama sonunda çıktığında, çıkış durumu kaybolur.

Başka bir yerde bahsedilen konsol tabanlı C++ başlatıcısını kullanmak yerine Prompt'ın START /WAIT komutunu kullanarak pencereli bir uygulamayı başlatmak daha basit bir alternatiftir. Bu, pencereli uygulamayı başlatır, çıkmasını bekler ve ardından ErrorLevel içinde ayarlanmış olan işlemin çıkış durumu ile Komut İstemi komutuna geri döner.

start /wait something.exe
echo %errorlevel%
227
Gary

Dahili ERRORLEVEL Değişkenini kullanın:

echo %ERRORLEVEL%

Ancak bir uygulamanın ERRORLEVEL !

92
Adam Rosenfield

Hata kodunu tam olarak eşleştirmek istiyorsanız (örneğin, 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 0, errorlevel> = 0 ile eşleşir. if /? bölümüne bakın.

18
Curtis Yallop

Konsola bağlı olmayan bir program kullanılırken düzgün çalışmayabilir, çünkü çıkış kodunuz olduğunu düşünüyorsanız o uygulama hala çalışıyor olabilir. C++ 'da 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;
}
14
dmihailescu

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

https://ss64.com/nt/errorlevel.html okunuyor, aşağıdakilere dikkat çeker:

CMD ve .BAT toplu iş dosyalarının hata seviyelerini ayarlama şekli arasında önemli bir fark vardır:

'Yeni' iç komutları çalıştıran eski bir .BAT toplu komut dosyası: APPEND, ASSOC, PATH, İstemi, FTYPE ve SET yalnızca bir hata oluştuğunda ERRORLEVEL değerini ayarlar. Bu nedenle, toplu komut dosyasında iki komutunuz varsa ve ilk başarısız olursa, ikinci komut başarılı olduktan sonra bile ERRORLEVEL ayarlanmış olarak kalır.

Bu hata ayıklamayı bir BAT komut dosyasında zorlaştırabilir, bir CMD toplu komut dosyası daha tutarlıdır ve çalıştırdığınız her komuttan sonra ERRORLEVEL değerini ayarlar.

Bu, art arda komutları yerine getirdiğim için kedere son vermeme neden oldu, ancak ERRORLEVEL bir başarısızlık durumunda bile değişmeden kalacaktı.

5
RockDoctor

Bir noktada, doğru bir şekilde günlük olaylarını Cygwin'den Windows Olay günlüğüne itmem gerekiyordu. WEVL'deki mesajların özel olmasını, doğru çıkış kodunun, ayrıntıların, önceliklerin, mesajın, vb. Olmasını istiyorum. Böylece bunun 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"

İşte geçici dosya içeriği bölümü:

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'de olayları yaratmanın bir işlevi:

__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ı yürütün ve __create_event öğesini çağırın:

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