Очень простое решение для запуска нескольких команд, записанных в пакетном файле, с подавлением стандартного вывода, записанного для обработки STDOUT , и сообщений об ошибках, записанных для обработки STDERR , с выходом из пакетного файла при первом запуске выход из команды или исполняемого файла с кодом выхода больше или равен 1
:
@echo off
goto MainCode
reg.exe add HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 0 /f
reg.exe add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 0 /f
:MainCode
title Disable UAC
for /F "useback skip=2 delims= eol=" %%I in ("%~f0") do (
if "%%~I" == ":MainCode" exit /B
echo %%I
%%I >nul 2>nul
if errorlevel 1 exit /B
)
Этот пакетный файл выполняет все непустые строки, определенные в пакетном файле ниже второй строки из-за skip=2
в FOR командной строке цикла и строки метки :MainCode
.
Эти командные строки не могут содержать ссылки на переменные среды с кодом, как предусмотрено, поскольку ссылки на переменные среды не будут расширяться командным процессором Windows перед выполнением. Конечно, можно использовать команду call
для принудительного дополнительного разбора командной строки во время выполнения цикла FOR для расширенных ссылок на переменные среды.
Командные строки между goto MainCode
и :MainCode
также не могут содержать операторы перенаправления, такие как <
, >
, >>
и |
. Перенаправления выполняются cmd.exe
выполнением командного файла. Командный процессор Windows должен распознать их уже при разборе командной строки перед выполнением. Поэтому, когда cmd.exe
анализирует командную строку %%I >nul 2>nul
перед выполнением, он распознает перенаправления >nul
и 2>nul
перед выполнением того, что в данный момент назначено для переменной цикла I
, но cmd.exe
никогда не распознает указанные перенаправления, указанные в командной строке присваивается переменной цикла I
.
См. Также Как интерпретатор сценариев команд Windows (CMD.EXE) анализирует сценарии?
Выполнение этого демонстрационного пакетного файла немедленно прекращается при выходе из первой команды / исполняемого файла со значением , большим или равным 1
. Команды IF и EXIT не изменяют переменную errorlevel
, поэтому вызывающий процесс получает код завершения неудачной команды / исполняемого файла.
Смотри также:
Код выхода командного файла: 0
, при отсутствии команды выхода со значением больше или равно 1
.
FOR открывает здесь пакетный файл, уже выполненный с помощью cmd.exe
, указанного с помощью %~f0
, который расширяется до диска + путь + имя + расширение самого пакетного файла из-за опции /F
и обрабатывает его построчно.
Параметр usebackq
необходим для получения полного имени пакетного файла, заключенного в "
, интерпретируемого как имя файла, строки которого должны быть обработаны, вместо интерпретации самого полного имени пакетного файла как строки для обработки с помощью ДЛЯ .
Опция skip=2
указывает FOR пропустить первые две строки открытого файла и начать обработку строк с третьей строки.
FOR с параметром /F
игнорирует всегда пустые строки. Строки, начинающиеся с точки с запятой, также игнорируются FOR при использовании опции /F
, поскольку eol=;
является определением конца строки по умолчанию. По этой причине eol=
используется для определения символа конца строки, в результате чего не игнорируются строки, начинающиеся с точки с запятой.
FOR по умолчанию разделяет каждую непустую строку, считанную из файла, на подстроки, используя обычный пробел и горизонтальную табуляцию в качестве разделителей строк, и назначает только первую строку с пробелом / символ табуляции с разделителями для указанной переменной цикла I
, Такое поведение разделения строк здесь не требуется. Вся строка, записанная в пакетном файле, должна быть присвоена переменной цикла I
. По этой причине delims=
задается для определения пустого списка символов, разделяющих строки, что полностью отключает режим разделения строк.
Основной код командного файла также может быть записан следующим образом:
title Disable UAC
del "%TEMP%\%~n0.log" 2>nul
for /F "useback skip=2 delims= eol=" %%I in ("%~f0") do (
if "%%~I" == ":MainCode" goto Finished
%%I >nul 2>>"%TEMP%\%~n0.log" || exit /B
)
:Finished
del "%TEMP%\%~n0.log" 2>nul
exit /B 0
В этом варианте пакетного файла команды / исполняемые файлы выполняются в режиме без вывода сообщений с подавлением стандартного вывода и выводом журнала ошибок в файл в папке для временных файлов с именем пакетного файла с расширением файла .log
.
Цикл завершается, если какая-либо команда / исполняемый файл завершается со значением, не равным 0, с кодом завершения последней выполненной команды / исполняемого файла или при достижении строки метки с удалением пустого файла журнала и кода выхода 0.
И еще более расширенная версия:
@echo off
goto MainCode
e TITLE Disable UAC
c echo Errors are log into file: "%TEMP%\%~n0.log"
p STEP 1: Disable User Account Control
r reg.exe add HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 0 /f
r reg.exe add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 0 /f
:MainCode
del "%TEMP%\%~n0.log" 2>nul
for /F "useback skip=2 tokens=1* eol=" %%I in ("%~f0") do (
if %%I == :MainCode del "%TEMP%\%~n0.log" 2>nul & exit /B 0
if %%I == c (
call %%J
) else if %%I == e (
%%J
) else if %%I == p (
echo(%%J
) else (
%%J >nul 2>>"%TEMP%\%~n0.log" || exit /B
)
)
В начале каждой командной строки есть один символ для выполнения в цикле FOR , управляющем выполнением этой строки. Символ отделяется от командной строки одним или несколькими пробелами или символом горизонтальной табуляции. Значение символов управления выполнением следующее:
- c ... вызовите эту командную строку с командой CALL , чтобы развернуть ссылки на переменные среды перед выполнением и не подавлять какие-либо выходные данные и не оценивать код выхода.
- e ... выполнить эту командную строку, не подавляя никаких выходных данных без оценки кода выхода.
- p ... эта строка содержит только текст для печати (в окне консоли) с помощью команды ECHO .
- r ... запустить эту командную строку с подавлением стандартного вывода и с выводом ошибки журналирования в файл журнала и с выходом из пакетного файла при выполнении кода выхода команды / исполняемого файла не
0
, что указывает не успешное исполнение.
(
между echo
и %%J
позволяет печатать также пустую строку, вставляя в командный блок строку только с p
.
Опция FOR delims=
заменяется на tokens=1*
. Здесь требуется поведение разделения строк FOR с разделителями по умолчанию и символом табуляции. Первая строка с пробелом / табуляцией должна быть присвоена переменной цикла I
, которая является здесь управляющим символом выполнения команды в начале каждой строки для выполнения или вывода соответственно метки :MainCode
. Все, что находится после пробелов / табуляций после первой строки, присвоенной переменной цикла I
, не должно делиться далее на пробелы / табуляции. По этой причине *
добавляется к tokens=1
, что говорит FOR назначить остаток строки после пробелов / табуляции после c
, e
, p
или r
для переменная следующего цикла в соответствии с таблицей ASCII , которая является символом J
.
Чтобы понять используемые команды и то, как они работают, откройте окно командной строки, выполните там следующие команды и полностью прочитайте все страницы справки, отображаемые для каждой команды.
call /?
... объясняет %~f0
... полное имя файла аргумента 0, то есть имя пакетного файла с расширением и полным путем, а также %~n0
, которое расширяется до просто имени файла пакетного файла без расширение файла и путь.
echo /?
exit /?
for /?
goto /?
if /?
... объясняет, что if ERRORLEVEL number
означает, что ERRORLEVEL
равно больше или равно number
и не равно number
, так как многие люди, не читающие помощь / документация думаю.
reg /?
reg add /?
См. Также одну строку с несколькими командами с использованием командного файла Windows для объяснения операторов &
и ||
.