सबरूटीन से बैच फ़ाइल बाहर निकलें


20

मैं एक सबरूटीन के अंदर से एक बैच फ़ाइल से कैसे बाहर निकल सकता हूं?

यदि मैं EXIT कमांड का उपयोग करता हूं, तो मैं बस उस लाइन पर लौटता हूं जहां मैंने सबरूटीन कहा था, और निष्पादन जारी है।

यहाँ एक उदाहरण है:

@echo off
ECHO Quitting...
CALL :QUIT
ECHO Still here!
GOTO END

:QUIT
EXIT /B 1

:END
EXIT /B 0

आउटपुट:

Quitting...
Still here!

अपडेट करें:

यह एक उचित उत्तर नहीं है, लेकिन मैंने कुछ इस तरह किया:

@echo off
CALL :SUBROUTINE_WITH_ERROR || GOTO HANDLE_FAIL
ECHO You shouldn't see this!
GOTO END

:SUBROUTINE_WITH_ERROR
ECHO Simulating failure...
EXIT /B 1

:HANDLE_FAIL
ECHO FAILURE!
EXIT /B 1

:END
ECHO NORMAL EXIT!
EXIT /B 0

का डबल-पाइप स्टेटमेंट:

CALL :SUBROUTINE_WITH_ERROR || GOTO HANDLE_FAIL

के लिए आशुलिपि है:

CALL :SUBROUTINE_WITH_ERROR 
IF ERRORLEVEL 1 GOTO HANDLE_FAIL    

मैं अभी भी यह जानना पसंद करूंगा कि क्या कॉलर को स्थिति को संभालने के बजाय उप-मार्ग से सीधे बाहर निकलने का एक तरीका है, लेकिन यह कम से कम काम पूरा करता है।


# 2 अद्यतन करें: जब एक उप-मार्ग से दूसरे उप-मार्ग के भीतर से कॉल किया जाता है, तो ऊपर दिए गए तरीके से कॉल किया जाता है, मैं इसी तरह से उप-मार्ग के भीतर से कॉल करता हूं:

CALL :SUBROUTINE_WITH_ERROR || EXIT /B 1

इस तरह, त्रुटि "मुख्य" तक वापस फैल जाती है, इसलिए बोलने के लिए। बैच का मुख्य भाग तब त्रुटि हैंडलर GOTO: FAILURE के साथ त्रुटि को संभाल सकता है

जवाबों:


21

इसे अपनी बैच फ़ाइल के शीर्ष पर जोड़ें:

@ECHO OFF
SETLOCAL

IF "%selfWrapped%"=="" (
  REM this is necessary so that we can use "exit" to terminate the batch file,
  REM and all subroutines, but not the original cmd.exe
  SET selfWrapped=true
  %ComSpec% /s /c ""%~0" %*"
  GOTO :EOF
)

तो आप बस कॉल कर सकते हैं:

  • EXIT [errorLevel] यदि आप पूरी फ़ाइल से बाहर निकलना चाहते हैं
  • EXIT /B [errorLevel] वर्तमान सबरूटीन से बाहर निकलने के लिए
  • GOTO :EOF वर्तमान सबरूटीन से बाहर निकलने के लिए

+1 वास्तव में उल्लेख करने के लिएGOTO :EOF
afrazier 22

1
बहुत अच्छा। मैं एक छोटा सा संशोधन, आवंटित कर दिया है %~0चर के बजाय true: if not "%selfwrapped%"=="%~0" ( set selfwrapped=%~0 .... )। इस तरह आप कई बैच स्क्रिप्ट में एक ही ट्रिक का उपयोग कर सकते हैं जो एक दूसरे को कहते हैं।
गोलेज़ट्रॉल

यह एक बेहतरीन उपाय है। क्या आपको लगता है कि यह समझाने के लायक है कि यह कैसे काम करता है? मुझे यह सब करने में एक मिनट का समय लगा और यह महसूस हुआ कि यह वास्तव में बैच फ़ाइल ( %~0) सभी तर्कों ( %*) के साथ नेस्टेड cmd.exe से है, और तर्क को दोहरे उद्धरण चिह्नों को संभालने के /sतरीके को नियंत्रित करने के लिए उपयोग किया जाता है %ComSpec%। कहते हैं।
सीन

@ सीन मुझे लगता है कि अधिकांश लोगों के लिए संक्षिप्तता अधिक उपयोगी है। 7 वर्षों से अधिक डॉक्स नहीं मांगे गए थे क्योंकि मैंने इसे लिखा था, इसलिए यह उच्च मांग में नहीं लगता है। मुझे यह भी लगता है कि लोगों को खुद को देख रहे लोगों के लिए कुछ मूल्य है और डॉक्स / टुकड़े करना नहीं है। लेकिन शायद अगर कुछ और लोग पूछें कि मैं कुछ जोड़ सकता हूं। यह एक सीडब्ल्यू भी है, इसलिए आप एक संपादन भी प्रस्तावित कर सकते हैं
मर्लिन मॉर्गन-ग्राहम

3

यह एक मामूली समायोजन के बारे में कैसे?

@echo off
ECHO Quitting...
CALL :QUIT
:: The QUIT subroutine might have set the error code so let's take a look.
IF ERRORLEVEL 1 GOTO :EOF
ECHO Still here!
GOTO END

:QUIT
EXIT /B 1

:END
EXIT /B 0

आउटपुट:

Quitting...

तकनीकी तौर पर यह सबरूटीन के भीतर से बाहर नहीं निकलता है। बल्कि, यह बस सबरूटीन के परिणाम की जांच करता है और वहां से कार्रवाई करता है।


2
धन्यवाद, कि निश्चित रूप से काम हो जाएगा, और अगर मुझे एक बेहतर जवाब नहीं मिल रहा है तो मुझे क्या करना होगा। हालाँकि, मुझे अपनी लंबी और जटिल बैच फ़ाइल में हर कॉल के बाद उस लाइन को चिपकाना नहीं था।
ब्राउन

1

यदि आप प्रक्रिया से वापस नहीं आना चाहते हैं, तो उपयोग न करें call: इसके बजाय उपयोग करें goto

@echo off
ECHO Quitting...
GOTO :QUIT
ECHO Will never be there!
GOTO END

:QUIT
EXIT /B 1

:END
EXIT /B 0

सवाल का मुद्दा यह है कि इसे सबरूटीन्स (यानी कॉल का उपयोग करके) से कैसे किया जाए, इसलिए इसका जवाब नहीं है।
स्टीव क्रेन

1

मैंने अपने बैच फ़ाइलों में त्रुटि हैंडलिंग को रखा। आप इस तरह त्रुटि संचालकों को कॉल कर सकते हैं:

CALL :WARNING "This is" "an important" "warning."

और यहाँ बैच फ़ाइल का अंत है:

::-------------------------------------------------------------------
::  Decisions
::-------------------------------------------------------------------
:INFO
IF "_DEBUG"=="true" (
  ECHO INFO: %~1
  IF NOT "%~2"=="" ECHO          %~2
  IF NOT "%~3"=="" ECHO          %~3
)
EXIT /B 0
:WARNING
ECHO WARNING: %~1
IF NOT "%~2"=="" ECHO          %~2
IF NOT "%~3"=="" ECHO          %~3
EXIT /B 0
:FAILURE
ECHO FAILURE: %~1
IF NOT "%~2"=="" ECHO          %~2
IF NOT "%~3"=="" ECHO          %~3
pause>nul
:END
ECHO Closing Server.bat script
FOR /l %%a in (5,-1,1) do (TITLE %TITLETEXT% -- closing in %%as&PING.exe -n 2 -w 1 127.0.0.1>nul)

1

यह वर्तमान संदर्भ और एक मूल संदर्भ से बाहर निकल जाएगा (यानी, जब एक callगहरी सबरूटीन स्क्रिप्ट के अंदर निष्पादित किया जाएगा):

(goto) 2>nul || exit /b

या, यदि आपको त्रुटि-रहित 0 की आवश्यकता है:

(goto) 2>nul || (
    type nul>nul
    exit /b
)

मूल रूप से, (goto) 2>nul1 के लिए एररलेवल सेट करता है (एक त्रुटि को आउटपुट किए बिना), मूल संदर्भ और कोड को दोहराता है, जब डबल पाइप को पेरेंट के संदर्भ में निष्पादित किया जाता है। type nul>nul0 पर सेट करता है।

युपीडी:

एक पंक्ति में दो से अधिक बार निष्पादन को वापस करने के लिए, श्रृंखला (goto) 2>nul ||इस तरह से कई :

(goto) 2>nul || (goto) 2>nul || (goto) 2>nul || (
    type nul>nul
    exit /b
)

यहाँ एक पुनरावर्ती उप-संदर्भ है जो संदर्भ को कई बार परिवर्तनशील बनाता है:

:Kill
(goto) 2>nul || (
    set /a depth=%1-1
    if %1 GEQ 1 (
        call:Kill !depth!
    )
    (goto) 2>nul || (type nul>nul)
)

जब एक पुनरावर्ती फ़ंक्शन से कॉल किया जाता है:

@echo off
setlocal EnableDelayedExpansion
call:Recurs 5
echo This won't be printed
exit /b

:Recurs
set /a ri+=1
echo %ri%
if %ri% LSS %1 (
    call:Recurs %1
)
echo This will be printed only once
call:Kill %1
exit /b

उत्पादन होगा:

1
2
3
4
5
This will be printed only once
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.