Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Batch file 如何从函数中退出批处理文件?_Batch File_Exit_Goto - Fatal编程技术网

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.