Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
492 views
in Technique[技术] by (71.8m points)

windows - Exit batch script from inside a function

I have a problem with my batch file. It builds several programs automatically by doing something like this:

  • set some compilation flags
  • run 'gmake all'
  • call the "check error level" function and if errorlevel 1, exit

So it looks like this:

set FLAG=1
...
gmake all
call :interactive_check
set OTHERFLAG=1
...
gmake all
call :interactive_check

There's 6 or 7 of these (and it might grow). So I made a function to check errorlevel instead of copy/pasting it at every step. The problem is this: the error checking is made through a function:

:interactive_check
if errorlevel 1 (
echo.
echo /!/!/!/!/!/!/!/!/!/!/!/!/!
echo Error in compilation process... exiting
echo /!/!/!/!/!/!/!/!/!/!/!/!/!
echo.
cd %root_dir%
exit /B 1
) ELSE (
echo.Continuing to next step
)
goto:eof

Now, when running it, the exit /B 1 simply exits the function, but not the batch file.

Do you know how to exit the complete batch file without having to copy/paste my "if errorlevel 1.." at every step?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

For a good solution see the part improved version

You can stop a batch at any point, also inside of nested function calls.

You only need to create a syntax error, for example with an empty block (), to suppress the error message, it can be executed in a call, and the stderr of the call is redirected to nul.

@echo off
setlocal enabledelayedexpansion

rem Do something
call :interactive_check

rem Do something
call :interactive_check

goto :eof

::::::::::::::::::::::::::
:interactive_check
if errorlevel 1 (
    echo.
    echo /!/!/!/!/!/!/!/!/!/!/!/!/!
    echo Error in compilation process... exiting
    echo /!/!/!/!/!/!/!/!/!/!/!/!/!
    call :halt 1
) ELSE (
    echo.Continuing to next step
)
goto :eof

:: Sets the errorlevel and stops the batch immediately
:halt
call :__SetErrorLevel %1
call :__ErrorExit 2> nul
goto :eof

:__ErrorExit
rem Creates a syntax error, stops immediately
() 
goto :eof

:__SetErrorLevel
exit /b %time:~-2%
goto :eof

2017-04-09 Improved version: Exit only the current batch, but not the caller batch

As @dbenham mentioned, there is a new technic for exception handling that can also be used for exiting only the current batch.

@echo off
echo Do something, detecting some fatal error
call :ExitBatch 3
exit /b

:ExitBatch [errorcode] - Exits only the current batch file, regardless how many CALLs
set _errLevel=%1
REM *** Remove all calls from the current batch from the call stack
:popStack
(
    (goto) 2>nul
    setlocal DisableDelayedExpansion    
    call set "caller=%%~0"
    call set _caller=%%caller:~0,1%%
    call set _caller=%%_caller::=%%
    if not defined _caller (
        REM callType = func
        rem set _errLevel=%_errLevel%
        goto :popStack
    )   
    (goto) 2>nul
    endlocal
    cmd /c "exit /b %_errLevel%"
)
echo NEVER REACHED
exit /b

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...