Лучшая практика - тестирование пакетных команд для ErrorLevel - PullRequest
0 голосов
/ 10 января 2019

Мой пакетный файл выполняет несколько команд редактирования реестра, и я хочу реализовать условие, если указанные команды редактирования реестра возвращают уровни ошибок. Мой вопрос: следует ли мне обернуть эти команды в функцию или создать условные уровни ошибок после КАЖДОЙ команды реестра? Мое беспокойство по поводу переноса этих команд в функцию заключается в том, что не каждая команда будет проверена. Я хочу убедиться, что каждая команда проверена и возвращает уровень ошибки.

Блок кода для переноса команд в функции может быть неправильным или отсутствующим фрагментом. Не уверен, нужно ли мне включать EXIT в конце каждой функции? Это отдельно от многошагового пакетного скрипта.

TITLE Disable UAC
ECHO STEP 1: Disable User Account Control
reg add HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 0 /f
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 0 /f

IF %ERRORLEVEL% NEQ 0 ECHO An error was found w/ error code of: %ERRORLEVEL%

или

:disable_uac
TITLE Disable UAC
ECHO STEP 1: Disable User Account Control
reg add HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 0 /f
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 0 /f

call :disable_uac
IF %ERRORLEVEL% NEQ 0 ECHO An error was found w/ error code of: %ERRORLEVEL$

Что касается первого фрагмента кода, я предполагаю, что условное значение ERRORLEVEL будет возвращать только код ошибки команды LAST, а не оба?

Обновленный код:

@echo off
goto ErrorCheck

SetLocal EnableDelayedExpansion

ECHO STEP 1: Copy Folder
robocopy "C:\Users\!username!\Documents\WindowsSetup\Training_Videos" "C:\Users\!username!\Desktop\Training_Videos" /e /copyall
CMD /K

:ErrorCheck
title Disable UAC
for /F "useback skip=2 delims= eol=" %%I in ("%~f0") do (
    IF "%%~I" == ":ErrorCheck" exit /B
    ECHO %%I
    %%I >>"C:\errorlog.log"
    if errorlevel 1 exit /B & ECHO You have encountered an issue. Look at Error Log for more information
)

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Я бы сделал это, используя условное выполнение, например ::100100

@echo off
CALL :DISABLEUAC || GOTO :ERRHANDLER
GOTO :EOF

:DISABLEUAC
ECHO STEP 1: Disable User Account Control
reg add HKEY_CURRENT_USER\... /f || GOTO :EOF
reg add HKEY_LOCAL_MACHINE\... /f || GOTO :EOF
GOTO :EOF

:ERRHANDLER
ECHO An error was found w/ error code of: %ERRORLEVEL%
GOTO :EOF
  • В подпрограмме DISABLEUAC используйте условное выполнение для выхода из подпрограммы в случае сбоя команды

  • В главном модуле вызовите подпрограмму и используйте условное выполнение для перехода к обработчику ошибок в случае сбоя подпрограммы.

0 голосов
/ 12 января 2019

Очень простое решение для запуска нескольких команд, записанных в пакетном файле, с подавлением стандартного вывода, записанного для обработки 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 для объяснения операторов & и ||.

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