Подтвердить что ты не робот

Командный интерпретатор Windows: как получить код выхода первой команды

В приведенном ниже примере я запускаю nmake, а затем перенаправляю STDOUT/STDERR на tee, который затем отправляет его на экран, а также в файл журнала. Проблема в том, что я пытаюсь захватить код выхода для nmake, а не tee. Мне нужен код выхода из nmake, а не tee.

nmake | tee output.txt
4b9b3361

Ответ 1

Вы можете подумать, что можете сделать что-то вроде следующего, но это не сработает.

(nmake & call set myError=%%errorlevel%%) | tee output.txt

Проблема заключается в механизме работы каналов Windows. Каждая сторона трубы выполнена в собственной оболочке CMD. Таким образом, любая переменная окружения, которую вы там установите, исчезнет после завершения команды. Кроме того, задержка раскрытия% errorlevel% более сложна из-за дополнительного уровня синтаксического анализа и потому, что оболочка CMD имеет контекст командной строки вместо пакетного контекста.

Вы могли бы сделать что-то вроде этого:

(nmake & call echo %%^^errorlevel%% ^>myError.txt) | tee output.txt
for /f %%A in (myError.txt) do echo nmake returned %%A
del myError.txt

Или вы можете встроить уровень ошибки в ваш output.txt:

(nmake & call echo nmakeReturnCode: %%^^errorlevel%%) | tee output.txt
for /f "tokens=2" %%A in ('findstr /b "nmakeReturnCode:" output.txt') do echo nmake returned %%A

Оба решения выше предполагают, что вы запускаете команды в пакетном скрипте. Если вместо этого вы выполняете команды из командной строки, то оба вышеуказанных решения требуют
%^^errorlevel% вместо %%^^errorlevel%%.

Но, учитывая, что nmake не требует ввода данных пользователем, и, как правило, он быстрый, поэтому мониторинг в реальном времени, вероятно, не является проблемой, тогда простейшее решение кажется

nmake >output.txt
set myError=%errorlevel%
type output.txt
echo nmake returned %myError%


Обратите внимание - при работе с конвейерами Windows есть много тонких сложностей. Хорошая справка: почему задержанное расширение завершается неудачно, когда находится внутри переданного блока кода? , Я рекомендую прочитать вопрос и все ответы. Выбранный ответ имеет лучшую информацию, но другие ответы помогают обеспечить контекст.

РЕДАКТИРОВАТЬ 2015-06-02

Я недавно обнаружил, что вы можете использовать макросы DOSKEY для чистого хранения и получения ERRORLEVEL с любой (или обеих) сторон канала, не прибегая к временному файлу. Я получил идею от пользователя DosTips Эда Дайрина по адресу http://www.dostips.com/forum/viewtopic.php?p=41409#p41409. Макросы DOSKEY не могут быть выполнены через пакет, но определения сохраняются после выхода из ENDLOCAL и CMD/C!

Вот как бы вы использовали это в вашей ситуации:

(nmake & call doskey /exename=err err=%%^^errorlevel%%) | tee output.txt
for /f "tokens=2 delims==" %%A in ('doskey /m:err') do echo nmake returned %%A

Если вы хотите, вы можете добавить еще одну команду в конце, чтобы очистить определение ошибки "макрос" после того, как вы получили значение.

doskey /exename=err err=