从子程序退出批处理文件

从子程序退出批处理文件

如何从子程序内部退出批处理文件?

如果我使用 EXIT 命令,我只需返回到调用子程序的行,然后继续执行。

以下是一个例子:

@echo off
ECHO Quitting...
CALL :QUIT
ECHO Still here!
GOTO END

:QUIT
EXIT /B 1

:END
EXIT /B 0

输出:

Quitting...
Still here!

更新:

这不是一个正确的答案,但我最终做了类似的事情:

@echo off
CALL :SUBROUTINE_WITH_ERROR || GOTO HANDLE_FAIL
ECHO You shouldn't see this!
GOTO END

:SUBROUTINE_WITH_ERROR
ECHO Simulating failure...
EXIT /B 1

:HANDLE_FAIL
ECHO FAILURE!
EXIT /B 1

:END
ECHO NORMAL EXIT!
EXIT /B 0

双管语句:

CALL :SUBROUTINE_WITH_ERROR || GOTO HANDLE_FAIL

是以下的简写:

CALL :SUBROUTINE_WITH_ERROR 
IF ERRORLEVEL 1 GOTO HANDLE_FAIL    

我仍然很想知道是否有办法直接退出子程序,而不必让 CALLER 处理这种情况,但这至少可以完成工作。


更新#2:当从另一个子程序中调用一个子程序时,以上述方式调用,我从子程序内部调用如下:

CALL :SUBROUTINE_WITH_ERROR || EXIT /B 1

这样,错误就会传播回“主”部分。然后,批处理的主要部分可以使用错误处理程序 GOTO :FAILURE 来处理错误

答案1

将其添加到批处理文件的顶部:

@ECHO OFF
SETLOCAL

IF "%selfWrapped%"=="" (
  REM this is necessary so that we can use "exit" to terminate the batch file,
  REM and all subroutines, but not the original cmd.exe
  SET selfWrapped=true
  %ComSpec% /s /c ""%~0" %*"
  GOTO :EOF
)

然后你只需调用:

  • EXIT [errorLevel]如果你想退出整个文件
  • EXIT /B [errorLevel]退出当前子程序
  • GOTO :EOF退出当前子程序

答案2

这个小调整怎么样?

@echo off
ECHO Quitting...
CALL :QUIT
:: The QUIT subroutine might have set the error code so let's take a look.
IF ERRORLEVEL 1 GOTO :EOF
ECHO Still here!
GOTO END

:QUIT
EXIT /B 1

:END
EXIT /B 0

输出:

Quitting...

从技术上来说,这并不是从子程序中退出。相反,它只是检查子程序的结果并从那里采取行动。

答案3

这将退出当前上下文和父上下文(即,当在一个call深层子程序脚本内执行时将退出):

(goto) 2>nul || exit /b

或者,如果您需要错误级别 0:

(goto) 2>nul || (
    type nul>nul
    exit /b
)

基本上,(goto) 2>nul将错误级别设置为 1(不输出错误),将执行返回到父上下文,并在父上下文中执行双管道后的代码。type nul>nul将错误级别设置为 0。

更新:

要连续两次返回执行,(goto) 2>nul ||请像这样链接几次:

(goto) 2>nul || (goto) 2>nul || (goto) 2>nul || (
    type nul>nul
    exit /b
)

这是一个递归子程序,用于返回不同次数的上下文:

:Kill
(goto) 2>nul || (
    set /a depth=%1-1
    if %1 GEQ 1 (
        call:Kill !depth!
    )
    (goto) 2>nul || (type nul>nul)
)

从递归函数调用时:

@echo off
setlocal EnableDelayedExpansion
call:Recurs 5
echo This won't be printed
exit /b

:Recurs
set /a ri+=1
echo %ri%
if %ri% LSS %1 (
    call:Recurs %1
)
echo This will be printed only once
call:Kill %1
exit /b

输出将是:

1
2
3
4
5
This will be printed only once

答案4

我将错误处理放在批处理文件中。您可以像这样调用错误处理程序:

CALL :WARNING "This is" "an important" "warning."

以下是该批处理文件的结尾:

::-------------------------------------------------------------------
::  Decisions
::-------------------------------------------------------------------
:INFO
IF "_DEBUG"=="true" (
  ECHO INFO: %~1
  IF NOT "%~2"=="" ECHO          %~2
  IF NOT "%~3"=="" ECHO          %~3
)
EXIT /B 0
:WARNING
ECHO WARNING: %~1
IF NOT "%~2"=="" ECHO          %~2
IF NOT "%~3"=="" ECHO          %~3
EXIT /B 0
:FAILURE
ECHO FAILURE: %~1
IF NOT "%~2"=="" ECHO          %~2
IF NOT "%~3"=="" ECHO          %~3
pause>nul
:END
ECHO Closing Server.bat script
FOR /l %%a in (5,-1,1) do (TITLE %TITLETEXT% -- closing in %%as&PING.exe -n 2 -w 1 127.0.0.1>nul)

相关内容