エラーが発生したときにバッチファイルを終了するにはどうすればよいですか?


290

同じ実行可能ファイルをさまざまなパラメーターで何度も呼び出すバッチファイルがあります。呼び出しの1つが任意のレベルのエラーコードを返した場合、すぐに終了させるにはどうすればよいですか?

基本的に、MSBuildと同等のものが必要ですContinueOnError=false


2
スクリプトを実行するコマンドシェルは何ですか?DOS / Win9xのcommand.comまたはWin2k +のcmd.exe?それは世界に違いをもたらすので、質問の編集でそれを明確にしていただけませんか?
Mihai Limbășan 2009

回答:


299

チェックerrorlevelしてif、文、及びexit /b(出口Bの 0以外の値のみATCHファイル全体ではなく、cmd.exeのプロセス)。

same-executable-over-and-over.exe /with different "parameters"
if %errorlevel% neq 0 exit /b %errorlevel%

エラーレベルの値をバッチファイルの外に伝播したい場合

if %errorlevel% neq 0 exit /b %errorlevel%

しかし、これが内部にあるfor場合は、少し注意が必要です。次のようなものが必要になります。

setlocal enabledelayedexpansion
for %%f in (C:\Windows\*) do (
    same-executable-over-and-over.exe /with different "parameters"
    if !errorlevel! neq 0 exit /b !errorlevel!
)

編集:コマンドごとにエラーを確認する必要があります。cmd.exe / command.comバッチには、グローバルな「エラー時のgoto」タイプのコンストラクトはありません。また、XPまたはVistaでのバッチハッキングで負のエラーレベルに遭遇したことはありませんが、CodeMonkeyごとにコードを更新しました。


11
ファイル全体に対して一度それを述べる方法はありますか?「エラー後藤」または同様の何か?
ジョシュコドロフ2009

3
マイナスのエラーレベルチェックの場合は+1。否定的な結果のためにスクリプトが静かに失敗しました。
devstuff '16

1
注意:enabledelayedexpansionはCRITICALであり、if / elseまたはその他のブロックにも必要です
MarcH

1
@ system-PAUSE表示されている最初の2つの「if」の間に違いはありますか?
simpleuser '20

1
遅延拡張の有効化/無効化、またはコマンド拡張機能(に必要neq)の有効化/無効化はif not errorlevel 1 exit /B、Microsoftのサポート記事「コマンドリダイレクト演算子の使用」およびコマンドif /?ウィンドウでの実行時のヘルプ出力で説明されているように、使用に関係ありません。現在のエラーレベル(終了コード)は、によるバッチファイルの処理の終了時に保持されますexit /B。注:exitパラメーターを使用/Bするには、有効なコマンド拡張機能が必要です。GOTO:EOF
Mofi 2017年

252

|| goto :label各行に追加して、を定義し:labelます。

たとえば、次の.cmdファイルを作成します。

@echo off

echo Starting very complicated batch file...
ping -invalid-arg || goto :error
echo OH noes, this shouldn't have succeeded.
goto :EOF

:error
echo Failed with error #%errorlevel%.
exit /b %errorlevel%

バッチファイルサブルーチンの終了に関する質問も参照してください。


4
それはほとんどのシェルスクリプト言語では非常に一般的なイディオムだし、それはよく読み:「それが失敗した場合にこれを行う、またはこの..」
家禽

3
私は手動で行番号の追跡保つためにSETを使用しますcommand || (SET ErrorLine=102 && goto :error)
サンドロック

1
@MarcelValdezOrozcoこれは||、最初に作成されたものだと私には思えます。特にgotoではないかもしれませんが、Fowlが述べたように「これをエラーで実行してください」私の質問は、これがすべてのゼロ以外の終了コードで機能するかどうかです。ポジティブのみ?
jpmc26 2013

3
@ jpmc26はい、ありますcmd /k exit -1 && echo success || echo fail。自分で証明してください--印刷に失敗します。
鶏2013

2
次のようなラベルでも回避できますcommand || exit /b %errorlevel%
Johannes Brodwall

94

一番短い:

command || exit /b

必要に応じて、終了コードを設定できます。

command || exit /b 666

また、ログに記録することもできます。

command || echo ERROR && exit /b

4
/ bを終了すると、元々失敗した終了コードが返されますか?
フランクSchwieterman

5
@FrankSchwieterman、はい、%ERRORLEVEL%あなたがを呼び出すときは触れられていないexit /bので、エラーコードが転送されます
Benoit Blanchon

24

1つのマイナーアップデートで、「if errorlevel 1」のチェックを次のように変更する必要があります...

IF %ERRORLEVEL% NEQ 0 

これは、XPでは負の数をエラーとして取得できるためです。0 =問題なし、それ以外は問題あり。

また、DOSが「IF ERRORLEVEL」テストを処理する方法を覚えておいてください。チェックしている番号がその番号以上の場合はtrueを返します。特定のエラー番号を探している場合は、255から始めて作業を進める必要があります。


1
Windows標準の内部および外部コマンドは、負の値で終了することはありません。Microsoftは、Environment.ExitCode Propertyに関するMSDNの記事などで、プログラムの作成者に負の値で終了するよう警告しています。実際、アプリケーションが成功した場合に使用する終了コードと、さまざまなエラーの場合に常に終了コードを見つける必要があります。HTMLヘルプワークショップは、ユーザーの期待に反する MSの例の.chmファイル正常にコンパイルした後にエラーを返します
Mofi 2017年

17

以下は、一連のコマンドを実行し、それらのいずれかが失敗した場合に終了するBASHおよびWindows CMDのポリグロットプログラムです。

#!/bin/bash 2> nul

:; set -o errexit
:; function goto() { return $?; }

command 1 || goto :error

command 2 || goto :error

command 3 || goto :error

:; exit 0
exit /b 0

:error
exit /b %errorlevel%

私は過去にこのタイプのものを複数プラットフォームの継続的統合スクリプトに使用しました。


10

私は、OR形式のコマンドを好んでいます(各コマンドの後にifがあるのではなく)。ただし、これを行う素朴な方法command || exit /b %ERRORLEVEL%間違っています。

これは、バッチが変数が使用されているときではなく、最初に読み取られたときに変数を展開するためです。これは、command上の行のが失敗した場合、バッチファイルは正常に終了しますが、戻りコード0で終了することを意味します%ERRORLEVEL%。これは、行の先頭にあるの値だからです。明らかに、これはスクリプトでは望ましくないため、次のように遅延拡張を有効にする必要 があります。

SETLOCAL EnableDelayedExpansion

command-1 || exit /b !ERRORLEVEL!
command-2 || exit /b !ERRORLEVEL!
command-3 || exit /b !ERRORLEVEL!
command-4 || exit /b !ERRORLEVEL!

このスニペットはコマンド1〜4を実行し、それらのいずれかが失敗すると、失敗したコマンドと同じ終了コードで終了します。


1

多くの場合、外部プログラムまたはバッチスクリプトは終了コードを返さないため、ERRORLEVELに常に依存することはできません。

その場合、次のようなエラーの一般的なチェックを使用できます。

IF EXIST %outfile% (DEL /F %outfile%)
CALL some_script.bat -o %outfile%
IF NOT EXIST %outfile%  (ECHO ERROR & EXIT /b)

そして、プログラムがコンソールに何かを出力する場合は、それもチェックできます。

some_program.exe 2>&1 | FIND "error message here" && (ECHO ERROR & EXIT /b)
some_program.exe 2>&1 | FIND "Done processing." || (ECHO ERROR & EXIT /b)

1

どのように試しても、msbuildが失敗した場合でも、エラーレベルは常に0のままです。だから私は私の回避策を構築しました:

プロジェクトをビルドし、ログをBuild.logに保存します

SET Build_Opt=/flp:summary;logfile=Build.log;append=true

msbuild "myproj.csproj" /t:rebuild /p:Configuration=release /fl %Build_Opt%

ビルドログで「0エラー」文字列を検索し、結果をvarに設定します

FOR /F "tokens=* USEBACKQ" %%F IN (`find /c /i "0 Error" Build.log`) DO (
    SET var=%%F
)
echo %var%

検索文字列を含む行数を示す最後の文字を取得します

set result=%var:~-1%

echo "%result%"

文字列が見つからない場合、エラー> 0、ビルド失敗

if "%result%"=="0" ( echo "build failed" )

そのソリューションは、バッチファイルでコマンド出力を変数として設定する方法に関するMechaflashの投稿に触発されました

およびhttps://ss64.com/nt/syntax-substring.html


1
カウントlssが10よりも大きい場合にのみ機能します。より良い; for /f %%F in ('type build.log^|find /c /i "0 Error") do set result=%%F。注:find "0 Error"も検索されます10 Errors
Stephan

-2
@echo off

set startbuild=%TIME%

C:\WINDOWS\Microsoft.NET\Framework\v3.5\msbuild.exe c:\link.xml /flp1:logfile=c:\link\errors.log;errorsonly /flp2:logfile=c:\link\warnings.log;warningsonly || goto :error

copy c:\app_offline.htm "\\lawpccnweb01\d$\websites\OperationsLinkWeb\app_offline.htm"

del \\lawpccnweb01\d$\websites\OperationsLinkWeb\bin\ /Q

echo Start Copy: %TIME%

set copystart=%TIME%

xcopy C:\link\_PublishedWebsites\OperationsLink \\lawpccnweb01\d$\websites\OperationsLinkWeb\ /s /y /d

del \\lawpccnweb01\d$\websites\OperationsLinkWeb\app_offline.htm

echo Started Build: %startbuild%
echo Started Copy: %copystart%
echo Finished Copy: %TIME%

c:\link\warnings.log

:error

c:\link\errors.log

4
回答に情報を追加してください。コードのブロックだけではあまり役に立ちません。
PoweredByOrange 2013

コメントを追加していないことに加えて、スニペットは機能を説明するのに適した候補のようには見えません。質問には完全に無関係な多くのものが含まれているようです。
ラウル・サリナス- Monteagudo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.