我有4个批处理文件,假设是a.bat、b.bat、c.bat和d.bat。现在这些批处理文件的调用方式是a.bat调用b.bat,b.bat调用c.call等等。
如果我在任何批处理文件中遇到任何错误,我想通过说发生错误来退出整个程序,并提及哪个批处理文件有问题。 我的问题是,我该怎么做?
这里我使用了
exit /b
但它只从当前的批处理文件中退出并移回到调用它的批处理文件中:
@echo. off
echo. this is batch 'a'
call b.bat
@echo. off
echo. this is batch 'b'
call c.bat
@echo. off
echo. this is batch 'c'
我在批次“C”中收到错误 - 然后它应该报告错误并退出,但它以某种方式移回批次“B”。关于如何退出嵌套批处理文件的任何想法?
您可以使用语法错误,这会立即停止批处理而不关闭命令窗口。
: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
()
此解决方案仅退出当前批处理文件,但不退出调用者批处理文件。
@echo off
echo Test
call :sub
echo Never visible
exit /b
:sub
echo In sub
call :exit-current-batch
echo Never visible
exit /b
:exit-current-batch
for /L %%# in (0 1 40) DO (
(goto) 2> NUL
call set "_tmp=%%0"
call set "_tmp=%%_tmp:~0,1%%"
call set "_tmp=%%_tmp::=%%"
if defined _tmp (
REM Current Batch entry found
exit /b
)
)
exit /b
你可以试试这个(
c.bat
):
@echo. this is batch 'c'
@pause
exit
您可以使用带有退出代码的错误级别,如下所述:http://www.robvanderwoude.com/errorlevel.php
特别是,如果您想执行手动错误,则 c.bat 或 b.bat 应明确指定退出代码
EXIT /b 1
(或您选择的多个),但如果您只想计算 Windows 自动错误,那么在运行 b.bat 或 c.bat 后,您可以直接编写
IF ERRORLEVEL 1 EXIT /b %ERRORLEVEL%
这会将相同的错误传播到下一个程序,因此如果您愿意,它们可以立即退出。优点是可以随时停止向上传播。
(编辑:要明确的是,无论您使用手动还是自动错误,这里提到的第二行代码在除底层程序之外的所有程序中都是必需的)
jeb 的致命语法错误方法有效,但它无法正确终止任何活动的 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,我在Why does a non-interactive批处理脚本认为我按下了control-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
如果 .BAT 文件位于 TakeCommand 下,请使用 CANCEL。