大多数解决方案仅适用于2个堆栈级别或带有屏幕错误消息。
因此,我想出了两个解决方案,我认为它们都比我在这里看到的更好。
没有SETLOCAL和ERRORLEVEL的复杂脚本解决方案
当以下条件满足时,可以使用此解决方案:
- 您有太多递归或条件函数,不知道程序何时终止
- 您不关心留在环境中的变量
- 您不关心errorLevel
CALL :leave 2>nul
:leave
()
GOTO :eof
解释:它将call :leave
放在堆栈级别上,并且伪参数2>nul
将错误消息发送到void,从而抑制该代码块中的错误。然后()
将生成致命错误,将杀死整个程序。
您甚至可以通过在主函数中设置SET空白或放置ENDLOCAL来删除变量CALL :leave
之前。
但是,在复杂的程序中,您不知道何时执行此操作。但在这种情况下,我想出了更好的解决方案...
我知道许多人在这里看到过这段代码:(GOTO) 2>nul & ENDLOCAL & EXIT /b %yourCode%
,但正如我所说,它只会终止当前函数并终止调用它的上一个函数。如果您有多个函数在堆栈上相互调用,则无法正常工作。因此,您可以强制发生多个错误:
(GOTO) 2>nul & (GOTO) 2>nul & (GOTO) 2>nul & ENDLOCAL & EXIT /b
然而,您不知道要执行多少次,如果过度执行,甚至可能会杀死:main并执行一个exit / b,这将关闭控制台。然后我有
使用SETLOCAL和ERRORLEVEL解决复杂脚本的方案
此解决方案适用于以下情况:
- 您有太多递归或条件函数,不确定程序何时终止
- 您不想留下残余变量
- 您检查errorLevel(可选)
SET dummy=iAmDefined
FOR /l %%i in (0, 1, 1000) do (
IF defined dummy (
(GOTO) 2>nul & IF NOT defined dummy (CMD /c EXIT /b %yourExitCode%)
)
)
它不会运行一千次,而只会运行尽可能少的次数,直到!dummy!错过分配。
除非您想要调试!dummy!回显,否则无需启用EnableDelayedExpansion。
示例:
@ECHO off
SETLOCAL EnableDelayedExpansion
SET dummy=iAmDefined
CALL :func3
:func1
ECHO i'm in func1
CALL :leave 2>nul
::GOTO :eof
:func2
ECHO i'm in func2
CALL: func1
::GOTO :eof
:func3
ECHO i'm in func3
CALL: func2
::GOTO :eof
:leave
ECHO ===leaving===
FOR /l %%i in (1, 1, 1000) of (
IF defined dummy (
(GOTO) & ECHO %%i !dummy! & IF NOT defined dummy (CMD /c EXIT /b 555)
)
)
::GOTO :eof
::ENDLOCAL
退出 e 解释:
-- 1 call (called func3)
i'm in func3 -- 2 calls (called func2)
i'm in func2 -- 3 calls (called func1)
i'm in func1 -- 4 calls (called leave)
===leaving===
1 iAmDefined -- rollback :leave
2 iAmDefined -- rollback :func3
3 iAmDefined -- rollback :func2
4 iAmDefined -- rollback :func1
5 !dummy! -- rollback :main before unset dummy
new CMD and exit after unset dummy
在第5个虚拟点之前仍然设置了(GOTO),但ECHO是在之后。
:EOF被注释以说明这些gotoes未被使用
call :interactive_check
替换为if errorlevel 1 goto error
即可。复制粘贴前者和后者之间没有太大区别。 :) - atzz