#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