2012-05-10 86 views
8

我寫檢查目錄一個簡單的功能:如何從函數內退出批處理文件?

: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 

我不明白爲什麼程序就不會轉到後停止:結束被稱爲。我有另一個功能,使用相同的方法來停止該程序,它工作正常。

:PRINT_USAGE 
echo Usage: 
echo ------ 
echo <file usage information> 
goto:end 

在這種情況下,程序在調用後會停止:end;爲什麼這不起作用:direxist?感謝您的幫助!

+0

可能重複http://stackoverflow.com/questions/3227796/exit-batch-script-函數內部) – Nathan

回答

12

我想你在這裏混合callgoto陳述。

批處理文件中的標籤可以與callgoto一起使用,但行爲不同。
如果call這樣的功能當函數到達文件的末尾或者明確exit /bgoto :eof(如您goto :end)將返回。

因此,如果您使用標籤作爲函數,則無法取消批次。

然而,goto到一個標籤,不會返回給調用者。

但也有一種方法可以從函數中退出批處理。
您可以創建語法錯誤,這會迫使批處理停止。

@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 
+3

除了無法返回到調用批處理腳本之外,此解決方案還可以防止在批處理終止時出現的隱式ENDLOCAL,從而導致不必要的浪費環境更改。 – dbenham

+0

請參閱http://stackoverflow.com/a/25474648/1012053以獲得一種乾淨的技術,以便在正常終止SETLOCAL的CALLed例程中退出批處理。 – dbenham

5

jeb's solution works great。但在任何情況下都可能不合適。它有2個潛在的缺點:

1)語法錯誤將停止所有批處理。所以如果一個批處理腳本調用你的腳本,並且你的腳本被語法錯誤暫停,那麼控制權不會返回給調用者。這可能是不好的。

2)通常,當批處理終止時,每個SETLOCAL都有一個隱式ENDLOCAL。但致命的語法錯誤終止批處理沒有隱含的ENDLOCAL!這個可以有:-(見我DosTips發佈SETLOCAL continues after batch termination!更多信息,討厭的後果。

更新2015年3月20日一個乾淨的方式立即終止所有批處理見https://stackoverflow.com/a/25474648/1012053

另一種在函數中暫停批處理文件的方法是使用EXIT命令,該命令將完全退出命令行界面,但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」和傑布的版本命名爲「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 

> 

一個潛在的缺點是,不保留到環境的變化。這可以通過在退出前寫environent到一個臨時文件,然後回讀中部分解決。

@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)變量將不會被妥善保存。

+0

+1,還不錯,你有優勢,臨時變量被刪除 – jeb

+0

@jeb - 我在想,環境變量設置的損失可能是一個缺點。但我明白你的觀點。退出條件之前可能有任何數量的臨時變量設置不應保留。如果有任何必須保留的變量,可以將它們選擇性地寫入臨時文件,並在CMD返回時進行恢復。 – dbenham

1

這裏是我的解決方案,如果所有被檢查的錯誤級別 我在我所有的呼叫(內部或外部)

@echo off 
call :error message&if errorlevel 1 exit /b %errorlevel%< 
@echo continuing 
exit /b 0 
:error 
@echo in %0 
@echo message: %1 
set yes= 
set /p yes=[no]^|yes to continue 
if /i "%yes%" == "yes" exit /b 0 
exit /b 1 
+0

我從你的帖子中學到了一些新東西。 %0的回聲是我從來沒有想過的(對於一個函數)。謝謝! – djangofan

1

如果使用exit /b X從函數退出添加測試errolevel將支持嵌套程序那麼它會將ERRORLEVEL設置爲X的值。如果ERRORLEVEL非零,則可以使用||conditional processing symbol執行命令。從這個腳本

@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. 
[從函數內部退出批處理腳本(指
相關問題