Пакет Windows: не может выйти из вызываемой подпрограммы - всегда возвращается, даже если goto: END - PullRequest
4 голосов
/ 19 марта 2012

У меня есть подпрограмма, которая вызывается для проверки ERRORLEVEL.
Подпрограмма вызывает другие подпрограммы для регистрации сообщений, отправки электронной почты и выхода из сценария.Идет к :END, затем возвращается к stmt после вызова

@echo off
echo starting...
call:checkTime
echo +++ after CT
GOTO:END

:checkTime
echo the time is %TIME%
goto:END
goto:EOF

:END

Ответы [ 2 ]

4 голосов
/ 19 марта 2012

Вопрос сформулирован плохо, но я думаю, что понимаю (особенно если сконцентрируюсь на названии)

Моя интерпретация вашей проблемы:

В различных точкахв вашем пакетном файле вы проверяете ОШИБКУ.Всякий раз, когда вы обнаруживаете ошибку, вы хотите выполнить некоторую стандартную обработку ошибок, а затем выйти из пакетного сценария.Вы попытались создать подпрограмму для выполнения стандартной обработки, но подпрограмма возвращается к вызывающей стороне вместо выхода из сценария.Ваш вопрос: как заставить принудительно завершить процедуру обработки ошибок вместо возврата к вызывающей стороне?

Ответ:

Если ни одно из ваших обнаружений ошибок не происходит в вызываемомподпрограммы, то вы можете просто ПОЛУЧИТЬ свой процессор ошибок вместо того, чтобы вызывать его.

Если вы хотите иметь возможность вызывать подпрограмму и выходить из другой вызываемой подпрограммы, тогда вы можете продолжать использовать оператор CALL, но завершите процедуру обработки ошибок с помощью EXIT вместо GOTO :EOF или GOTO :END.

Добавление в ответ на комментарий

Да, GOTO не может передавать параметры,и подпрограмма CALLed всегда будет возвращаться вызывающей стороне (если процедура не заканчивается EXIT)

И да, EXIT закроет текущую оболочку CMD, которая обычно закрывает окно консоли.

НО... вы можете заставить пакетный файл выполнить себя через другую оболочку CMD, чтобы EXIT не закрывал окно!

Единственный потенциальный недостаток, который я вижу, это chВремена для среды будут потеряны, как только завершится пакетный файл (и запускающая его оболочка CMD).Это может или не может быть проблемой для вас.

@echo off
if "%~1" equ "_GO_" goto :main
cmd /c ^""%~f0" _GO_ %*^"
exit /b

:main
shift /1
echo %%1=%1  %%2=%2

echo before call
call :exitRoutine
:: should not get here
echo after call
exit /b

:exitRoutine
echo exiting batch file witin exitRoutine
exit
3 голосов
/ 20 марта 2012

Да, это ожидаемое поведение: подпрограмма, вызываемая с помощью команды CALL, может завершиться тремя различными способами: выполнить EXIT [/B], выполнить GOTO :EOF или просто достичь конца файла.Все три способа вызывают возврат к вызывающей программе.К тому времени «команда GOTO теперь принимает целевую метку: EOF, которая передает управление в конец текущего файла пакетного скрипта. Это простой способ выйти из файла пакетного скрипта без определения метки».(из GOTO /?), так что на самом деле второй и третий методы одинаковы.

Если вы хотите иногда возвращаться из подпрограммы, а иногда - завершать вызывающую программу, тогда ваша подпрограмма НЕ МОЖЕТ быть выполнен через CALL, но другим способом.Если вы хотите передать параметры подпрограмме, то это должен быть отдельный файл .BAT, который будет выполняться через его имя с параметрами и без вызова, например:

subprogram param1 param2 ...

Таким образом, чтобыэта подпрограмма, чтобы «вернуться» к вызывающей программе, должна знать, в какой пакетный файл и в какую строку она должна возвращаться.Эта информация может быть установлена ​​вызывающей программой через переменные;вызывающая программа также должна определить, работает ли она обычным образом или потому что возвращена подпрограмма false.Вы можете сделать это следующим образом:

main.bat:

@echo off
rem If this is a false subroutine return: complete it
if "%1" == "return" goto %2
rem Do my usual business
rem . . .
rem Execute the subprogram as subroutine
set caller=main
set returnPoint=label23
subprogram param1 param2
:label23
rem Continue after subprogram return...

subprogram.bat:

rem Do my business
rem . . .
rem To return to the caller:
%caller% return %returnPoint%
rem . . .
rem To terminate here, execute EXIT /B, GOTO :EOF, or just reach the end

Извините, нет простого способа сделать это ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...