2012-05-10 1 views
8

私は、ディレクトリをチェックするために書かれたシンプルな機能を持っているエンドプログラムは後藤後に停止しないだろう、なぜ私は理解していない 関数内からバッチファイルを終了するにはどうすればよいですか?</p> <pre><code>:direxist if not exist %~1 ( echo %~1 could not be found, check to make sure your location is correct. goto:end ) else ( echo %~1 is a real directory goto:eof ) </code></pre> <p>:

:end 
endlocal 

のように書かれている:最後に呼ばれてきました。私はプログラムを停止するために同じメソッドを使用し、正常に動作する別の関数があります。

:PRINT_USAGE 
echo Usage: 
echo ------ 
echo <file usage information> 
goto:end 

この場合、プログラムは次の呼び出し後に停止します。なぜこれはうまくいかないでしょう:direxist?ご協力ありがとうございました!

+0

可能重複(http://stackoverflow.com/questions/3227796/exit-batch-script-関数内から) – Nathan

答えて

12

callgotoの文をここに混ぜているとします。

バッチファイルのラベルは、callまたはgotoで使用できますが、動作が異なります。
場合call関数は、ファイルの終わりか(あなたのgoto :endのように)明示的なexit /bまたはgoto :eofに達したときに、それが戻りますように機能

したがって、ファンクションというラベルを使用すると、バッチをキャンセルすることはできません。

ただし、ラベルにgotoは、を返しません。を呼び出し元に返します。

しかし、ファンクションからバッチを終了する方法もあります。
構文エラーを作成すると、強制的にバッチが停止します。

@echo off 
call :label hello 
call :label stop 
echo Never returns 
exit /b 

:label 
echo %1 
if "%1"=="stop" goto :halt 
exit /b 

:halt 
call :haltHelper 2> nul 

:haltHelper 
() 
exit /b 
+3

このソリューションは、呼び出し側のバッチスクリプトに戻すことができないことに加えて、バッチ終了時に発生すると思われる暗黙のENDLOCALも防ぎ、望ましくない持続的変化をもたらします。 – dbenham

+0

SETLOCALを正しく終了するCALLedルーチン内からバッチ処理を終了するクリーンなテクニックについては、http://stackoverflow.com/a/25474648/1012053を参照してください。 – dbenham

5

jebのソリューションは素晴らしいです。しかし、それはすべての状況において適切ではないかもしれません。

1)構文エラーは、すべてバッチ処理を停止します。したがって、バッチスクリプトがスクリプトを呼び出し、スクリプトが構文エラーで停止した場合、制御は呼び出し元に返されません。それは悪いかもしれない。

2)通常、バッチ処理が終了すると、すべてのSETLOCALに暗黙のENDLOCALがあります。しかし、致命的な構文エラーはバッチ処理を終了します暗黙のENDLOCALなし!これは私のDosTips詳細についてはSETLOCAL continues after batch termination!を投稿ください:-(厄介な結果をもたらす可能性がある。

アップデート2015年3月20日すぐにすべてのバッチ処理を終了するきれいな方法についてhttps://stackoverflow.com/a/25474648/1012053を参照してください。

関数内でバッチファイルを停止するもう1つの方法は、コマンドシェルを完全に終了するEXITコマンドを使用することですが、CMDを少し独創的に使用すると、問題を解決するのに役立ちます。

@echo off 
if "%~1" equ "_GO_" goto :main 
cmd /c ^""%~f0" _GO_ %*^" 
exit /b 

:main 
call :label hello 
call :label stop 
echo Never returns 
exit /b 

:label 
echo %1 
if "%1"=="stop" exit 
exit /b 

私は「daveExit.bat」という名前の私のバージョンと私のPCの「jebExit.bat」という名前のジェブのバージョンの両方を持っています。

私は、このバッチスクリプト

@echo off 
echo before calling %1 
call %1 
echo returned from %1 

そして、ここを使用してそれらをテストEXITソリューションの結果

>test jebExit 
before calling jebExit 
hello 
stop 

>test daveExit 
before calling daveExit 
hello 
stop 
returned from daveExit 

> 

一つの潜在的な欠点は、環境への変更が保存されていないということですされています。それは部分的に終了する前に一時ファイルにenvironentを書き込み、その後にそれを読み戻すことで解決することができます。

@echo off 
if "%~1" equ "_GO_" goto :main 
cmd /c ^""%~f0" _GO_ %*^" 
for /f "eol== delims=" %%A in (env.tmp) do set %%A 
del env.tmp 
exit /b 

:main 
call :label hello 
set junk=saved 
call :label stop 
echo Never returns 
exit /b 

:label 
echo %1 
if "%1"=="stop" goto :saveEnvAndExit 
exit /b 

:saveEnvAndExit 
set >env.tmp 
exit 

しかし、価値の改行文字(0x0Aを)持つ変数が適切に保存されません。

+0

+1また、素敵な、あなたは一時的な変数が削除されるという利点があります。 – jeb

+0

@jeb - 私は環境変数の設定の損失が不利になるかもしれないと考えていました。しかし、私はあなたのポイントを見ます。保存してはならない終了条件の前には、一時変数設定がいくつあってもかまいません。保存する必要がある変数がある場合、それらは一時的に一時ファイルに書き込まれ、CMDが復帰すると復元されます。 – dbenham

1

は、ここでは、機能を終了しexit /b Xを使用している場合は、私はすべての私のコール(内部または外部)

@echo off 
call :error message&if errorlevel 1 exit /b %errorlevel%< 
@echo continuing 
exit /b 0 
:error 
@echo in %0 
@echo message: %1 
set yes= 
set /p yes=[no]^|yes to continue 
if /i "%yes%" == "yes" exit /b 0 
exit /b 1 
+0

私はあなたの記事から新しいことを学びました。 %0のエコーは、私が(ファンクションに対して)全く新しいことではありません。ありがとう! – djangofan

1

でerrolevelのためのテストを追加し、すべてがERRORLEVEL がチェックされている場合は、ネストされたルーチンをサポートしています私の解決策ですERRORLEVELXの値に設定します。 ERRORLEVELがゼロでない場合、||conditional processing symbolを使用してコマンドを実行できます。このスクリプトから

@echo off 
setlocal 
call :myfunction PASS || goto :eof 
call :myfunction FAIL || goto :eof 
echo Execution never gets here 
goto :eof 

:myfunction 
    if "%1"=="FAIL" ( 
     echo myfunction: got a FAIL. Will exit. 
     exit /b 1 
    ) 
    echo myfunction: Everything is good. 
    exit /b 0 

出力は次のとおりです。[関数内から終了バッチスクリプト]の

myfunction: Everything is good. 
myfunction: got a FAIL. Will exit. 
関連する問題