Пакет: как перейти от вложенной программы к выходу из основной программы?

#batch-file #goto

#пакетный файл #goto

Вопрос:

У меня есть control_script.cmd, который работает как есть, но его немного сложно читать. В принципе, я хочу завершить работу своего скрипта, когда первая программа возвращает ошибку.

 set text=converting something...
call %libdir%1_convert_xlsx.cmd 
set rvalue=%errorlevel%
call :check_errorlevel !rvalue! "!text!"
if !rvalue! geq 1 goto :my_error_handler

set text=loading something...
call %libdir%2_load_something.cmd 
set rvalue=%errorlevel%
call :check_errorlevel !rvalue! "!text!"
if !rvalue! geq 1 goto :my_error_handler

:check_errorlevel 
set rvalue=%~1
set text=%~2
echo do something with rvalue and text
exit /b 0

:my_error_handler
exit /b 1
  

было бы намного лучше, если бы я мог переместить if-предложение в часть check_errorlevel, например

 call %libdir%1_convert_xlsx.cmd 
call :check_errorlevel %errorlevel% "converting something..."

call %libdir%2_load_something.cmd  
call :check_errorlevel %errorlevel% "loading something..."

:check_errorlevel 
set rvalue=%~1
set text=%~2
echo do something with rvalue and text
if !rvalue! geq 1 goto :my_error_handler
exit /b 0


:my_error_handler
exit /b 1
  

Но здесь я сталкиваюсь с проблемой, что:my_error_handler не определен в :check_errorlevel, и я не вижу другого способа перейти непосредственно от:check_errorlevel к концу моего cmd. Есть ли какие-либо?

С наилучшими пожеланиями, Питер

Комментарии:

1. Есть ли какая-либо причина, по которой вы не просто используете If not errorlevel 0 (command) , а не ресурсоемкую функцию вызова? — Учитывая, что вы уже используете отложенное расширение, его можно легко записать в виде макроса, чтобы зафиксировать уровень ошибок, выполнить тест и вывести строку, относящуюся к тестируемой команде, с помощью модификации подстроки. Метод макроса позволяет избежать добавления другого стека среды в командный процессор

2. Причина, по которой вы не можете просто выйти из /b до конца скрипта, заключается в том, что при использовании call вызываемая метка выполняется как независимая дочерняя среда, которая возвращает управление родительской среде после выполнения.

3. @T3RR0R: дочерняя среда; да, но что такое обход? причина: на самом деле, check_errorlevel содержит дерево операторов if-else . Я просто сокращаю код.

4. Обход заключается в том, чтобы не использовать подпрограмму, которая должна сначала вернуть управление скрипту. Вы могли бы сделать hard exit , однако я предполагаю, что здесь это нежелательно.

5. хорошо, может быть, я просто попробую ваш стиль макроса.

Ответ №1:

% Итак, после подсказки @aschipfl я перейду к приведенному ниже коду. На самом деле мне все еще нужно это протестировать, но у меня здесь хорошее предчувствие.

 call %libdir%1_convert_xlsx.cmd 
call :check_errorlevel %errorlevel% "converting something..." || goto :my_error_handler

call %libdir%2_load_something.cmd  
call :check_errorlevel %errorlevel% "loading something..." || goto :my_error_handler

goto :all_fine

:check_errorlevel 
set rvalue=%~1
set text=%~2
echo do something with rvalue and text
if %rvalue% GEQ 1 ( set my_errorlevel = 1 ) else ( set my_errorlevel = 0 )
REM notice that this errorlevel only transfers the input-errorlevel and is not an errorlevel by itself.
exit /b %my_errorlevel%

:my_error_handler
exit /b 1

:all_fine
exit /b 0
  

редактировать: {} в () благодаря Стефано

Комментарии:

1. if %rvalue% GEQ 1 { set my_errorlevel = 1 } else { set my_errorlevel = 0 } конечно, не работает. Это должно быть if %rvalue% GEQ 1 (set my_errorlevel=1) else (set my_errorlevel=0)

Ответ №2:

Вот пример стиля макроса, о котором я упоминал

 @Echo off amp; Setlocal EnableExtensions EnableDelayedExpansion
rem // macro definition within delayed expansion environment requires exclaimation marks to be thrice escaped.
rem // outer For %%n loop uses If ()Else construct to capture the trailing string within the output variable at the time of expansion.
Set "CHKErr=For %%n in (1 2)Do If %%n==2 (If Not "^^^!Errorlevel^^^!"=="0" (Echo/Failed [^^^!Errorlevel^^^!] - ^^^!Output^^^!amp;Endlocal amp;Goto :EOF)Else (Echo/Success - ^^^!Output^^^!))Else Set Output="
 Call :truelabel 2> Nul
 %CHKErr%:truelabel
 Call :falselabel 2> Nul
 %CHKErr%:falselabel
 Echo/You'll never see this on fail.
Goto :Eof

:truelabel
Exit /B 0