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?
app.exe & echo %errorlevel%
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?
app.exe & echo %errorlevel%
Yanıtlar:
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.
@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%.
echo Exit Code is $LastExitCode
%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 (...)
stringdeğil int, etkin EQ/ kullanamayacağınız anlamına gelir NEQ.
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%
ifveya içinde olması for. !errorlevel!Bunun yerine, bu cevapta açıklandığı gibi kullanmayı düşünün .
Yerleşik ERRORLEVEL Değişkenini kullanın:
echo %ERRORLEVEL%
Ancak bir uygulamanın ERRORLEVEL adında bir ortam değişkeni tanımladığını unutmayın !
$LastExitCodePowerShell'de çağrılır .
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 .
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;
}
.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ı.
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