Windows 批处理:无法退出调用的子例程 - 即使 goto:END 也始终返回



我有一个子例程,它被调用来检查ERRORLEVEL
该子例程调用其他子例程来记录消息、发送电子邮件,然后退出脚本。它进入:END,然后在调用后返回stmt

@echo off
echo starting...
call:checkTime
echo +++ after CT
GOTO:END
:checkTime
echo the time is %TIME%
goto:END
goto:EOF
:END

这个问题措辞拙劣,但我想我理解(尤其是如果我专注于标题)

我对您的问题的解释:

在批处理文件中的不同点,您可以检查ERRORLEVEL。每当检测到错误时,都希望执行一些标准的错误处理,然后退出批处理脚本。您试图创建一个子例程来执行标准处理,但该子例程返回给调用者,而不是退出脚本。您的问题是,如何强制您的错误处理例程退出,而不是返回到调用者?

答案:

如果您的错误检测都没有发生在调用的子程序中,那么您可以简单地转到错误处理器,而不是调用它。

如果希望能够调用该例程并从另一个调用的例程中退出,则可以继续使用CALL语句,但使用EXIT而不是GOTO :EOFGOTO :END终止错误例程。

回应评论的附录

是的,GOTO无法传递参数,CALLed例程将始终返回给调用者(除非例程以EXIT结束)

是的,EXIT将关闭当前CMD shell,这通常会关闭控制台窗口。

但是。。。您可以让批处理文件通过另一个CMD shell自行执行,这样EXIT就不会关闭窗口!

我看到的唯一潜在缺点是,一旦批处理文件(以及运行它的CMDshell)终止,对环境的更改就会丢失。这对你来说可能是个问题,也可能不是。

@echo off
if "%~1" equ "_GO_" goto :main
cmd /c ^""%~f0" _GO_ %*^"
exit /b
:main
shift /1
echo %%1=%1  %%2=%2
echo before call
call :exitRoutine
:: should not get here
echo after call
exit /b
:exitRoutine
echo exiting batch file witin exitRoutine
exit

是的,这是预期的行为:通过CALL命令调用的子例程可能以三种不同的方式结束:执行EXIT [/B]、执行GOTO :EOF或刚好到达文件的末尾。这三种方式都会导致返回到调用程序。顺便说一句,"GOTO命令现在接受一个目标标签:EOF,它将控制权转移到当前批处理脚本文件的末尾。这是一种不用定义标签就能退出批处理脚本的简单方法。"(来自GOTO /?),所以第二种和第三种方法实际上是一样的。

如果有时要从子程序返回,但有时要终止调用程序,则子程序不能通过CALL执行,而是以其他不同的方式执行。如果您想将参数传递给子程序,那么它必须是一个单独的.BAT文件,该文件将通过其带有参数和NO调用的名称执行,例如:

subprogram param1 param2 ...

这样,为了让这个子程序"返回"到调用程序,它必须知道哪个批处理文件以及它必须返回的行。该信息可以由调用程序通过变量设置;调用程序还必须确定它是以正常方式运行,还是因为返回了false子例程。你可以这样做:

main.bat:

@echo off
rem If this is a false subroutine return: complete it
if "%1" == "return" goto %2
rem Do my usual business
rem . . .
rem Execute the subprogram as subroutine
set caller=main
set returnPoint=label23
subprogram param1 param2
:label23
rem Continue after subprogram return...

子程序.bat:

rem Do my business
rem . . .
rem To return to the caller:
%caller% return %returnPoint%
rem . . .
rem To terminate here, execute EXIT /B, GOTO :EOF, or just reach the end

抱歉,没有简单的方法。。。

最新更新