4

У меня есть консольное приложение. Взаимодействие с этим приложением осуществляется через TCP/IP.Получение кода выхода приложения началось с команд «cmd» и «start»

У меня также есть тестовая среда для него, которая в основном представляет собой набор скриптов BATCH (... не моя ошибка). Что такое тестовая структура для каждого теста, в основном это:

  1. start /min "myapplication.exe" и дождаться получения подтверждения о том, что приложение запущено.
  2. отправлять команды через TCP/IP в это приложение, получать его ответы и проверять, соответствуют ли тайминги и значения тем, что ожидается в результате конкретного теста.

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

Итак, я попытался следующие:

start /min cmd /c "myapplication.exe || echo %errorLevel% > exitcode.txt"

, а затем позже в тестовых сценариях,

if exist exitcode.txt (
    set /p exitcode=<exitcode.txt 
    echo ERROR: myapplication.exe returned exitcode %exitcode%. 
    goto error 
) else (
    goto do_processing 
) 

, но по какой-то странной причине, никогда не появляется текстовый файл, даже если Иногда я получаю диалог о сбое приложения, и хотя я принудительно делаю его неудачным с известным кодом нулевого выхода. Тест проходит через do_processing и (конечно) приводит к сбою.

EDIT Когда я бегу

start /min cmd /c "nonsense || echo %errorLevel% > test.txt"

Я иногда получить текстовый файл, содержащий строку 9009, но в других случаях, что текстовый файл содержит строку 0, или иногда 1, .. .Что за...?!

EDIT2 Если вы наберете

cmd /k "nonsense || echo %errorLevel%"

(обратите внимание на опцию /k), вы видите 0 печатаемые в новом окне, но если вы затем введите echo %errorlevel%, вы получите 1 ...

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

Любые идеи о том, что может происходить здесь?

+0

Вам нужно будет использовать параметр/wait, чтобы получить код выхода. Во-первых, это должно привести к тому, что вы начнете использовать старт. Избегайте пожара и забывания, когда требуется проверка ошибок. –

+0

@Hans Passant: Я думаю, что это не сработает, потому что если вы используете 'start', код выхода не будет передан вызывающему скрипту. Вместо этого вы должны использовать 'call'. Он ведет себя как 'start/wait', но передает переменные. Проверьте это: http://stackoverflow.com/questions/13257571/call-command-vs-start-with-wait-option – MichaelS

+0

@HansPassant: но 'start/wait' означает, что выполнение скрипта будет заблокировано. Затем скрипт не может загореться командами ... –

ответ

7

Нормальное расширение, например %errorLevel%, возникает, когда инструкция анализируется, и вся командная строка CMD/C обрабатывается за один проход, поэтому значение, которое вы получаете, является значением, существовавшим до выполнения команд (всегда 0).

Подробное описание вы можете получить по адресу https://stackoverflow.com/a/4095133/1012053. Вначале трудно понять и понять значение фаз, но это стоит усилий.

Чтобы решить вашу проблему, вы должны отложить расширение переменной до тех пор, пока ваш exe не запустится.

У вас есть два варианта:

Вариант 1) Используйте ВЫЗОВ, чтобы получить задержанный раунд расширения.

В пакетном файле вы должны удвоить проценты. Но команды, запускаемые с использованием CMD/C, выполняются в контексте командной строки, а не в пакетном режиме. Удвоение процентов не работает в командной строке.

Вместо этого вы должны ввести символ управления (cmd.exe escape) в имя переменной. Первая фаза расширения происходит до того, как экраны обработаны, поэтому он ищет имя с кареткой и не находит его. Когда не найден, синтаксический анализатор командной строки сохраняет исходный текст, когда переменная не найдена. Затем обрабатываются специальные символы, и побег расходуется. Поэтому, когда происходит CALL раунд расширения, он видит правильное имя переменной.

start /min cmd /c "myapplication.exe || call echo %^errorLevel% > exitcode.txt" 

Вариант 2) Использование задержкой расширения

Delayed синтаксис расширение !errorlevel! вместо %errorlevel%. Но прежде чем вы сможете использовать его, должно быть включено замедленное расширение. В пакетном скрипте вы должны использовать setlocal enableDelayedExpansion, но это не работает в контексте командной строки. Вместо этого вы должны использовать опцию cmd.exe /v:on.

start /min cmd /v:on /c "myapplication.exe || echo !errorLevel! > exitcode.txt" 
+0

AAAAAARGH! Я не могу поверить, что снова упал! Это очень приятно, спасибо вам большое. Фу, чтобы думать о головных болях, которые это вызвало у многих людей ... –

+0

просто из любопытства: есть ли какое-либо преимущество/недостаток 'call' vs.' cmd/v: on'? –

+1

В этом случае не совсем. CALL сравнительно медленный, но только вступает в игру при выполнении многих итераций в замкнутом цикле - здесь не проблема. CALL также наносит ущерб цитируемым брошюрам, которые должны пройти (удваивает их), опять же не проблема. Отсроченное расширение разлагает расширение переменных FOR, значение которых содержит символ '!', Также не является проблемой здесь. – dbenham

1

Как пояснялось here, вы должны использовать call вместо start, чтобы иметь возможность оценить коды выхода. call запустит скрипт в той же среде переменных, в то время как start запустит его в новом, который не доступен из первого скрипта.

+0

... но код выхода записывается в * файл * в том же процессе, поэтому мне не нужно заботиться об определенной среде переменных ... –

+0

Вы можете написать код выхода с помощью '@echo% errorlevel% >> вывод.txt'. И именно по этой причине вы не можете использовать 'start'. 'start' не будет устанавливать допустимый% errorlevel% в вызывающем скрипте. Использование 'start' позволяет выполнить тест в фоновом режиме, но вы никогда не получите доступ к коду выхода. – MichaelS

+0

О, извините, я пропустил вас. – MichaelS

1

Другим решением может быть использование вместо &||

start myapplication.exe ^& echo %errorLevel% ^> exitcode.txt 

^ это побег символ, таким образом, что это оценивается внутри самого начала, а не снаружи, как объяснено here.

Это сработало для меня. Надеюсь, это поможет кому-то.