jeb 的解决方案效果很好。但这可能并不适用于所有情况。它有两个潜在的缺点:
1) 语法错误将停止所有批处理。因此,如果批处理脚本调用了您的脚本,并且您的脚本因语法错误而停止,则控制权不会返回给调用者。那可能很糟糕。
2) 通常,当批处理终止时,每个 SETLOCAL 都有一个隐式 ENDLOCAL。但是致命的语法错误会在没有隐式 ENDLOCAL 的情况下终止批处理!这可能会产生令人讨厌的后果 :-( 请参阅我的 DosTips post SETLOCAL 在批处理终止后继续!了解更多信息。
更新 2015-03-20 请参阅https://stackoverflow.com/a/25474648/1012053,了解立即终止所有批处理的干净方法。
在函数中停止批处理文件的另一种方法是使用 EXIT 命令,该命令将完全退出命令 shell。但是稍微创造性地使用 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
在我的 PC 上,我的版本名为“daveExit.bat”,jeb 的版本名为“jebExit.bat”。
然后我使用这个批处理脚本测试它们
@echo off
echo before calling %1
call %1
echo returned from %1
这是结果
>test jebExit
before calling jebExit
hello
stop
>test daveExit
before calling daveExit
hello
stop
returned from daveExit
>
EXIT 解决方案的一个潜在缺点是不会保留对环境的更改。这可以通过在退出之前将环境写入临时文件,然后再读回来部分解决。
@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) 的变量将无法正确保留。