Как завершить пакетный файл windows из подпрограммы "called"?

У меня есть пакетный файл windows, с несколькими подпрограммами в нем что-то вроде этого:

call :a
goto :eof

:a
call :b
goto :eof

:b
:: How do I directly exit here from here?
goto :eof

Я запускаю это в окне cmd на Vista.
Если я обнаруживаю ошибку где-то в пакетном файле, я хочу, чтобы она вышла с ненулевым уровнем ошибок. Есть ли что-нибудь, что я могу написать в подпрограмме :b, что заставит пакетный файл завершиться так.

  • я попробовал "exit", который закрывает все окно cmd. Это не то, чего я хочу.
  • Я попробовал "exit / B 1". Это возвращает нас к предыдущей процедуре. Чтобы использовать эту схему после каждого "вызова", мне нужно было бы тщательно написать "if errorlevel 1 exit /B 1 "после каждого "вызова", чтобы передать ошибку обратно в стек вызовов. Я бы предпочел не писать эту строчку после каждого звонка.

эта статья была интересной, но не альтернативы ведут себя так, как я хочу. http://www.computerhope.com/exithlp.htm

есть еще способ?

спасибо.

2 ответов


вы можете назвать свои подпрограммы так:

call :b||exit /b 1

что эквивалентно

call :b
if errorlevel 1 exit /b 1

это немного короче и экономит вам одну строку, но это все еще не идеально, я согласен.

кроме этого, я не вижу способа.

EDIT: хорошо, у меня есть способ, но это чистое зло™.

неправильно используя максимальный размер стека и, следовательно, предел рекурсии, мы создаем другую подпрограмму, которая просто исчерпывает стек рекурсивно называя себя:

@echo off
echo Calling a
call :a
echo Called a
goto :eof
:a
echo Calling b
call :b
echo Called b
goto :eof
:b
echo Trying to exit
call :exit
goto :eof
:exit
call :exit

это, однако, приведет к неприятному сообщению об ошибке

******  B A T C H   R E C U R S I O N  exceeds STACK limits ******
Recursion Count=704, Stack Usage=90 percent
******       B A T C H   PROCESSING IS   A B O R T E D      ******

кроме того, это займет около 2 секунд на моей машине.

вы можете подавить сообщение об ошибке, изменив call заявление следующим образом:

call :exit >nul 2>&1

который перенаправит все, что он хочет вывести в большую пустоту.

но учитывая время, необходимое для заполнения стека, я думаю, что первый вариант будет облегчающий.

Я также рассматривал использование второго пакетного файла, который при запуске без call по существу остановит первый. Но почему-то это не очень хорошо играет с подпрограммами. Развертывание стека вызовов, по-видимому, все еще происходит.


вы можете создать выход.файл bat, который убивает верхний файл bat по имени заголовка.

пример:

A. bat

@echo off
title A.bat
echo A.bat
call B.bat
echo A.bat

B. bat

@echo off
echo B.bat
exit.bat A.bat
echo B.bat

выход.летучая мышь!--9-->

@echo off
echo exit.bat
kill %1