Batch file 如何从函数中退出批处理文件?
我编写了一个简单的函数来检查目录:Batch file 如何从函数中退出批处理文件?,batch-file,exit,goto,Batch File,Exit,Goto,我编写了一个简单的函数来检查目录: :direxist if not exist %~1 ( echo %~1 could not be found, check to make sure your location is correct. goto:end ) else ( echo %~1 is a real directory goto:eof ) :结束写为 :end endlocal 我不明白为什么程序在goto:end被调用后不会停
:direxist
if not exist %~1 (
echo %~1 could not be found, check to make sure your location is correct.
goto:end
) else (
echo %~1 is a real directory
goto:eof
)
:结束写为
:end
endlocal
我不明白为什么程序在goto:end被调用后不会停止。我有另一个函数,它使用相同的方法来停止程序,并且工作正常
:PRINT_USAGE
echo Usage:
echo ------
echo <file usage information>
goto:end
:打印使用
回声使用:
回音------
回音
后藤:结束
在本例中,程序在调用:end;为什么这不适用于:direxist?谢谢你的帮助 我想您在这里混合了
call
和goto
语句
批处理文件中的标签可以与调用
或转到
一起使用,但行为不同。如果
调用此类函数,则当函数到达文件末尾或显式退出/b
或转到:eof
(如您的转到:结束
)时,它将返回
因此,如果将标签用作函数,则无法取消批处理
但是,goto
到标签将不会返回到调用方
使用synatx错误:
但也有一种方法可以从函数中退出批处理。
您可以创建语法错误,这将强制批处理停止。
但是它有一个副作用,本地(setlocal)变量将不会被删除
@echo off
call :label hello
call :label stop
echo Never returns
exit /b
:label
echo %1
if "%1"=="stop" goto :halt
exit /b
:halt
call :haltHelper 2> nul
:haltHelper
()
exit /b
使用CTRL-C:
创建类似于CTRL-C错误代码的错误代码也会停止批处理。
退出后,setlocal状态是干净的
见@dbenham的答案
使用高级异常处理:
这是最强大的解决方案,因为它能够删除任意数量的堆栈级别,它只能用于退出当前批处理文件,也可以用于显示堆栈跟踪。
它使用这样一个事实,即(goto)
,不带参数,从堆栈中删除一个元素。
请参见杰布的解决方案非常有效。但这可能并不适用于所有情况。它有两个潜在的缺点:
1) 语法错误将停止所有批处理。因此,如果一个批处理脚本调用了您的脚本,并且您的脚本由于语法错误而停止,那么控制不会返回给调用方。那可能很糟糕
2) 通常,当批处理终止时,每个SETLOCAL都有一个隐式ENDLOCAL。但是致命的语法错误终止批处理,而不使用隐式ENDLOCAL!这可能会产生恶劣的后果:-(有关更多信息,请参阅我的DosTips帖子)
更新2015-03-20有关立即终止所有批处理的干净方法,请参阅
在函数中暂停批处理文件的另一种方法是使用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
我的电脑上有我的名为“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
>
退出解决方案的一个潜在缺点是不会保留对环境的更改。这可以通过在退出之前将环境写入临时文件,然后将其读回来部分解决
@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)的变量将无法正确保留。我的解决方案将支持嵌套例程,如果所有例程都检查了errorlevel
我在所有调用(内部或外部)中添加errolevel测试
@echo关闭
呼叫:错误消息&if errorlevel 1退出/b%errorlevel%<
@回音继续
退出/b0
:错误
@在%0中回显
@回显消息:%1
确定是=
设置/p是=[否]^是继续
如果/i“%yes%”==“yes”退出/b 0
退出/b 1
如果使用exit/bx
退出函数,则它将ERRORLEVEL
设置为X
的值。如果ERRORLEVEL
非零,则可以使用|
执行命令
@echo off
setlocal
call :myfunction PASS || goto :eof
call :myfunction FAIL || goto :eof
echo Execution never gets here
goto :eof
:myfunction
if "%1"=="FAIL" (
echo myfunction: got a FAIL. Will exit.
exit /b 1
)
echo myfunction: Everything is good.
exit /b 0
此脚本的输出为:
myfunction: Everything is good.
myfunction: got a FAIL. Will exit.
+1,也很好,而且临时变量是removed@jeb-我认为失去环境变量设置可能是一个缺点。但我明白你的观点。在退出条件之前,可能有很多临时变量设置不应该保留。如果有任何变量必须保留ved时,可以有选择地将它们写入临时文件,并在CMD返回时还原。除了无法返回调用批处理脚本外,此解决方案还可以防止在批处理终止时出现隐式ENDLOCAL,从而导致不必要的延迟环境更改。有关从wi退出批处理的干净技术,请参阅精简一个正确终止SETLOCAL的被调用例程。我从您的帖子中学到了一些新的东西。%0的回音是我从未听说过的(对于一个函数)。谢谢!可能是的重复
myfunction: Everything is good.
myfunction: got a FAIL. Will exit.