Как установить% ERRORLEVEL% в cmd / c? - PullRequest
1 голос
/ 28 февраля 2020

Я хочу иметь возможность установить переменную среды %ERRORLEVEL% (также называемую « системная переменная ») равной произвольному значению в начале командной строки скрипт (т.е. cmd /c), работающий в PowerShell . Всякий раз, когда люди хотят установить %ERRORLEVEL% (1) , они делают следующее:

cmd /c "exit /b 3"
cmd /c "echo %ERRORLEVEL%" 

Однако, хотя %ERRORLEVEL% установлен на 3, когда приведено выше В обычной командной строке, если эти точные строки выполняются в PowerShell, переменная среды кода выхода имеет значение , а не , установленное на 3 и остается 0. Кроме того, вы не можете сделать следующее:

cmd /v:on /c "exit /b 3 & echo !ERRORLEVEL!"

Команда exit полностью прекращает выполнение команды (т. Е. cmd /c), и никакая другая команда после * 1028 не выполняется. * выполняется.

Поэтому я попытался выполнить следующую команду в PowerShell:

cmd /v:on /c "SET %ERRORLEVEL% = 4 & echo !ERRORLEVEL!"

Ожидаемый вывод - 4, но всегда выводит 0. Я не могу понять, почему я не могу SET переменную окружения %ERRORLEVEL%. Я использовал отложенное выполнение команды ( пример здесь ), но здесь не работает никакая путаница.

Кто-нибудь знает, почему команда SET %ERRORLEVEL% = 4 не работает?

Если вы не способны SET переменные окружения тогда как можно установить %ERRORLEVEL% на произвольное значение в строке команд, разделенных амперсандом (&), как указано выше?

1 Ответ

3 голосов
/ 29 февраля 2020

Если вы хотите сохранить возможный код выхода в переменной cmd.exe для позже используйте с exit, , сделайте , а не попробуйте установить ERRORLEVEL; вместо этого используйте имя пользовательской переменной ; например, ec (для e xit c ода):

# Execute in PowerShell
PS> cmd /v /c 'set "ec=3" & echo ... & exit /b !ec!'; $LASTEXITCODE
...
3

На стороне cmd.exe:

  • set "ec=3" устанавливает переменную ec в значение 3

    • Заключение пара имя-значение в "..." не является строго обязательной, но четко очерчивает конец значения и позволяет использовать значения со встроенными специальными символами, такими как &.

    • Значение переменной в дальнейшем может быть указано как %ec% ( up-front * расширение 1050 *) или !ec! ( задержка расширение, если включено через setlocal enabledelayedexpansion или через переключатель командной строки /v - см. help setlocal)

  • echo ... - пример команды, представляющей дополнительные команды

  • exit /b !ec! выходит со значением переменной ec в качестве кода выхода; обратите внимание, что на переменную по необходимости ссылаются как !ec!, а не %ec%, через отложенное расширение, потому что переменная была установлена ​​ как часть того же оператора .

    • Используете ли вы /b (выход только из текущего пакетного файла) или нет, здесь не имеет значения; В любом случае, оператор exit в этом случае определяет код завершения процесса экземпляра cmd.

Команды последовательность (безусловно выполняется один за другим) с оператором & как часть одного оператора.

На стороне PowerShell:

  • Аналог PowerShell для cmd.exe & - ;, разделитель операторов - позволяет размещать несколько операторов в одной строке.

  • $LASTEXITCODE - автоматическая c переменная PowerShell, которая содержит код завершения процесса самой последней исполняемой внешней программы, в данном случае cmd.exe s, со значением 3.


Кто-нибудь знает, почему команда SET %ERRORLEVEL% = 4 не работает?

Подводя итог полезной информации из комментариев к вопросу:

  • Принципиально не пытайтесь • переменная окружения dynamici c (псевдо) %ERRORLEVEL% - это автоматически , поддерживаемое cmd.exe для отображения кода выхода самой последней команды - см. нижнюю часть section.

  • Не ставьте пробелы вокруг = в присваивании переменной cmd.exe:

    • Пробелы (и) до = становится частью имени переменной .
    • Пробелы после становятся частью значения .
  • Не заключать имя целевой переменной в %...% (если вы не хотите косвенно установить переменная через другую переменную, значение которой содержит имя переменной для назначения).

set %ERRORLEVEL% = 4

Если %ERRORLEVEL% отражает 0 в начале последовательности команд, указанное выше назначение создает переменную с буквальным именем 0 (то есть значение %ERRORLEVEL%, за которым следует один пробел) , ш Значение шланга составляет 4 (то есть, один пробел, за которым следует 4).


Переменные в cmd.exe:

В основном, за исключениями, обсуждаемыми ниже, переменные в cmd.exe - это все переменные окружения .

В отличие от таких оболочек, как Bash и PowerShell, существует нет отдельного пространства имен для локальных переменных оболочки, которые не видны дочерние процессы.

Это имеет следующие последствия:

  • Предопределенные постоянные переменные среды, такие как %Path%, совместно используют то же пространство имен, что и пользовательские переменные, которые вы определяете с помощью команды SET, поэтому вам следует помнить о конфликтах имен.

  • Точно так же дочерний обрабатывает, что вы запускаете из cmd.exe сеансового / пакетного файла наследует пользовательских переменных, которые вы создали в сеансе.

    • Обратите внимание, что использование setlocal действительно не меняет это; setlocal - это cmd -внутренний механизм области видимости, который позволяет управлять временем жизни пользовательских переменных среды, локализуя их в область (пакетный файл), в которой был вызван setlocal, и удаляя их через последующий вызов endlocal или, неявно, в конце вложенного пакетного файла.

Пользовательские переменные являются переменными среды процесса только для процесса что go выходит за рамки процесса cmd.exe; постоянные Определения переменных среды должны создаваться и изменяться с помощью реестра , например, с помощью утилиты setx.exe.

В дополнение к предопределенным (постоянным) переменным среды и пользовательские (только для сеанса) переменные среды, cmd.exe поддерживает dynamici c псевдо-переменные среды, такие как %ERRORLEVEL% и %RANDOM% (см. список ниже):

  • Эти псевдопеременные среды имеют значения dynamici c, поддерживаемые самой cmd.exe ...

  • ... и они не видимы для дочерних процессов.

Примечание. Строго говоря, эти динамические переменные c включены только при включенных так называемых расширениях команд , но это правда по умолчанию (вы можете отключить их с помощью /E:OFF, но это не рекомендуется).

Поскольку эти переменные c не являются строго частью среда процесса , что дочерние процессы наследуют Копия, они не являются переменными среды , хотя help SET несколько смущающе называет их dynamici c переменными среды .

Вы не должны (и не можете) изменять эти переменные.

Если вы попытаетесь, то действительно произойдет следующее: вы shadow (переопределите) эти псевдопеременные с помощью действительные , пользовательские переменные среды, которые по определению имеют значения stati c.

Более поздний код, который полагается на переменные с таким именем, чтобы они имели свои обычные динамические c следовательно, поведение может давать сбой.

Список динамических c переменных , полученных из Windows 10 через help SET (выделение добавлено):

Если Командные расширения включены , то существует несколько динамических переменных среды , которые могут быть расширены, но которые не отображаются в списке переменных, отображаемых SET . Эти значения переменных вычисляются динамически каждый раз, когда значение переменной увеличивается. Если пользователь явно определяет переменную с одним из этих имен, то это определение переопределит динамическое c, описанное ниже:

  • %CD% - расширяется до текущего строка каталога.
  • %DATE% - расширяется до текущей даты, используя тот же формат, что и команда DATE.
  • %TIME% - расширяется до текущего времени, используя тот же формат, что и команда TIME.
  • %RANDOM% - расширяется до случайного десятичного числа от 0 до 32767.
  • %ERRORLEVEL% - расширяется до текущего значения ERRORLEVEL
  • %CMDEXTVERSION% - расширяется до текущей версии расширений командного процессора число.
  • %CMDCMDLINE% - расширяется до исходной командной строки, которая вызывала командный процессор.
  • %HIGHESTNUMANODENUMBER% - расширяется до максимального номера узла NUMA на этом компьютере.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...