从嵌套的batch file中退出

我有4个batch file,假设a.bat,b.bat,c.bat和d.bat。 现在这些batch file被调用,a.bat调用b.bat,b.bat调用c.call等等。

如果在任何batch file中出现任何错误,我想通过说错误发生而退出整个程序,并提及哪个batch file有问题。 我的问题是 ,我该怎么做?

在这里我使用了exit /b但是它只从当前的batch file中取出,并移回到从其调用的batch file中:

一只蝙蝠

 @echo. off echo. this is batch 'a' call b.bat 

b.bat

 @echo. off echo. this is batch 'b' call c.bat 

C.BAT

 @echo. off echo. this is batch 'c' 

我在“C”批处理中遇到一个错误 – 它应该报告一个错误并退出,但是它以某种方式回到批处理“B”。 任何想法如何退出嵌套的batch file?

你可以使用一个语法错误,这个停止立即停止批处理命令窗口。

:HALT函数只调用:__halt函数来抑制错误信息。

C.BAT

 @echo off echo this is batch 'c' echo An error occurs call :HALT exit /b :HALT call :__halt 2> nul exit /b :__halt () 

你可以试试这个( c.bat ):

 @echo. this is batch 'c' @pause exit 

杰布的致命的语法错误方法的作品,但它不正确终止任何活动的SETLOCAL。

例如,这里是fatalTest.bat:

 @echo off setlocal enableDelayedExpansion set test=AFTER main SETLOCAL call :sub echo returning from main NEVER REACHED exit /b :sub setlocal set test=AFTER sub SETLOCAL set test call :ExitBatch echo returning from sub2 NEVER REACHED exit /b :ExitBatch call :__exitBatch 2>nul :__ExitBatch for 

下面是示例运行输出,演示如何定义测试,并在批处理终止后仍启用延迟扩展:

 C:\test>fatalTest test=AFTER sub SETLOCAL C:\test>echo !test! AFTER sub SETLOCAL C:\test> 

现在不可能将环境恢复到预批处理状态。 CMD.EXE会话应该被终止。


这是一个改进的CtrlCTest.bat版本,可以在批终止时正确终止任何活动的SETLOCAL。 它使用一个令人惊讶的技术来编程“按”Ctrl-C,我了解了为什么一个非交互式的批处理脚本认为我已经按下了控制-C?

 @echo off setlocal enableDelayedExpansion set test=AFTER main SETLOCAL call :sub echo returning from main NEVER REACHED exit /b :sub setlocal set test=AFTER sub SETLOCAL set test call :ExitBatch echo returning from sub2 NEVER REACHED exit /b :ExitBatch - Cleanly exit batch processing, regardless how many CALLs if not exist "%temp%\ExitBatchYes.txt" call :buildYes call :CtrlC <"%temp%\ExitBatchYes.txt" 1>nul 2>&1 :CtrlC cmd /c exit -1073741510 :buildYes - Establish a Yes file for the language used by the OS pushd "%temp%" set "yes=" copy nul ExitBatchYes.txt >nul for /f "delims=(/ tokens=2" %%Y in ( '"copy /-y nul ExitBatchYes.txt <nul"' ) do if not defined yes set "yes=%%Y" echo %yes%>ExitBatchYes.txt popd exit /b 

这里是示例运行输出。 您可以看到延迟扩展不再处于活动状态,测试不再被定义:

 C:\test>CtrlCTest test=AFTER sub SETLOCAL C:\test>echo !test! !test! C:\test>set test Environment variable test not defined C:\test> 

您可以将:ExitBatch例程放置在驻留在PATH某处的独立ExitBatch.bat脚本中,然后任何批处理可以根据需要方便地调用该实用程序。

 @echo off :ExitBatch - Cleanly exit batch processing, regardless how many CALLs if not exist "%temp%\ExitBatchYes.txt" call :buildYes call :CtrlC <"%temp%\ExitBatchYes.txt" 1>nul 2>&1 :CtrlC cmd /c exit -1073741510 :buildYes - Establish a Yes file for the language used by the OS pushd "%temp%" set "yes=" copy nul ExitBatchYes.txt >nul for /f "delims=(/ tokens=2" %%Y in ( '"copy /-y nul ExitBatchYes.txt <nul"' ) do if not defined yes set "yes=%%Y" echo %yes%>ExitBatchYes.txt popd exit /b 

您可以使用退出代码的错误级别,如下所述: http : //www.robvanderwoude.com/errorlevel.php

特别是,如果你想做一个手动错误,那么c.bat或者b.bat应该显式地有一个退出代码

 EXIT /b 1 

(或者你选择的一些),但是如果你只是想让windows的自动错误来计算,那么在运行b.bat或c.bat之后,你可以直接写

 IF ERRORLEVEL 1 EXIT /b %ERRORLEVEL% 

这将传播相同的错误,直到下一个程序,所以他们可以立即退出,如果你愿意。 有优势,你可以停止向上传播,只要你想要的。

(编辑:要清楚,这里提到的第二行代码是必须的,除了最底层的程序,无论你是使用手动还是自动错误)

如果.BAT文件位于TakeCommand下,请使用CANCEL。