&&
и ||
не совпадают с IF / ELSE.
С IF / ELSE вам гарантировано, что будет срабатывать только одна ветвь.
Но || всегда будет отвечать на код возврата последней выполненной команды. Таким образом, с учетом такого заявления, как cmd1 && cmd2 || cmd3
, cmd3 будет запускаться в случае сбоя cmd1 или сбоя cmd2.
Учитывая вышесказанное, должно быть очевидно, что невозможно отменить код возврата (от нуля до нуля, от нуля до нуля), используя только &&
и ||
,
Очевидно, это можно сделать, если вы добавите GOTO, или CALL, или ... но я сомневаюсь, что это то, что вы хотите.
Я предполагаю, что вы хотите встроенную, автономную конструкцию, которая будет выполнять отрицание.
Похоже, вам удобно использовать% ERRORLEVEL%, но имейте в виду, что% ERRORLEVEL% отличается от кода возврата команды. Например, многие внутренние команды выполняются успешно, но они не устанавливают значение ERRORLEVEL равным 0, а оставляют значение без изменений. &&
и ||
операторы отвечают на истинный код возврата и не смотрят на ОШИБКУ.
Моя идея для отрицания ERRORLEVEL - использовать тестирование SET /A для деления на ноль. Но вы должны использовать отложенное расширение, если вы хотите исследовать ERRORLEVEL в той же строке, в которой установлено значение.
(2>null set /a 1/!ERRORLEVEL! &&call ||call)
Значение 2>null
скрывает сообщение об ошибке при делении на 0. &&call<space>
(с завершающим пробелом) устанавливает ERROLEVEL в 0, когда деление завершается успешно, а ||call
(без завершающего пробела) устанавливает ERRORLEVEL в 1 при делении на 0. Скобки позволяют безопасно использовать конструкцию inline.
Вы можете сохранить код в переменной и использовать его как простой макрос. Ниже приведен полный пример, демонстрирующий полное использование макроса %not%
.
@echo off
setlocal enableDelayedExpansion
:: Note the delayed expansion requires the quoted ! to be escaped as ^! while defining the macro
set "not=(2>nul set /a 1/^!errorlevel^!&&call ||call)"
for /l %%N in (-2 1 2) do (
call :setErrorLevel %%N & %not% && echo SUCCESS !errorlevel! || echo FAILURE !errorlevel!
echo(
)
exit /b
:setErrorLevel
echo Testing %1
exit /b %1
Важно, чтобы вы использовали одиночный &
перед %not%
чтобы он всегда выполнялся.
Очевидно, вам не нужно делать все встроенное:
@echo off
setlocal enableDelayedExpansion
:: Note the delayed expansion requires the quoted ! to be escaped as ^! while defining the macro
set "not=(2>nul set /a 1/^!errorlevel^!&&call ||call)"
for /l %%N in (-2 1 2) do (
call :setErrorLevel %%N
%not%
if errorlevel 1 (
echo FAILURE !errorlevel!
) else (
echo SUCCESS !errorlevel!
)
echo(
)
exit /b
:setErrorLevel
echo Testing %1
exit /b %1
Обратите внимание, что echo(
это просто способ печати пустой строки, который безопаснее использовать, чем echo.
..