Есть ли способ в пакетной версии script, чтобы консоль открывалась только при вызове из Windows Manager?

У меня есть пакет DOS script, который вызывает приложение java, которое взаимодействует с пользователем через пользовательский интерфейс консоли. Для аргумента, позвольте называть его runapp.bat, а его содержимое будет

java com.example.myApp

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

Я знаю следующие трюки:

  • добавьте команду pause в конце script. Это немного уродливо, если в командной строке вызывается runapp.bat.

  • создайте новую оболочку с помощью cmd /K java com.example.myApp Это лучшее решение, которое я нашел до сих пор, но оставляет дополнительную оболочку при вызове из командной строки, так что вызов exit фактически не закрывает оболочку.

Есть ли лучший способ?

Ответ 1

Смотрите этот вопрос: Обнаружение выполнения пакетного файла

Этот script не будет приостанавливаться, если он запускается из командной консоли, но если он дважды щелкнут в проводнике:

@echo off
setlocal enableextensions

set SCRIPT=%0
set DQUOTE="

:: Detect how script was launched
@echo %SCRIPT:~0,1% | findstr /l %DQUOTE% > NUL
if %ERRORLEVEL% EQU 0 set PAUSE_ON_CLOSE=1

:: Run your app
java com.example.myApp

:EXIT
if defined PAUSE_ON_CLOSE pause

Ответ 2

Я предпочитаю использовать %cmdcmdline%, как указано в комментарии к Патрику, чтобы ответить на другой вопрос (который я не нашел, хотя посмотрел). Таким образом, даже если кто-то решит использовать кавычки для вызова пакета script, он не будет вызывать ложное срабатывание.

Мое окончательное решение:

@echo off
java com.example.myApp %1 %2

REM "%SystemRoot%\system32.cmd.exe"   when from console
REM cmd /c ""[d:\path\script.bat]" "  when from windows explorer

@echo %cmdcmdline% | findstr /l "\"\"" >NUL
if %ERRORLEVEL% EQU 0 pause

Ответ 3

cmd /K java com.example.myApp & pause & exit

выполнит эту работу. Команда и будет выполнять команду один за другим. Если вы используете && вы можете сломаться, если не удастся.

Ответ 4

Включите эту строку в пакетный файл и дважды щелкните по пакетному файлу в проводнике:

cmd/k "script в этих кавычках, разделенных & &"

Например

cmd/k "cd../.. && dir & cd some_directory"

Полный набор параметров для cmd можно найти здесь

Ответ 5

Я часто использую альтернативные оболочки (в первую очередь TCC/LE от jpsoft.com) и подоболочки. Я обнаружил, что этот код работает для более широкого и более общего случая (и для него не требуется FINDSTR):

@echo off & setlocal
if "%CMDEXTVERSION%"=="" ( echo REQUIRES command extensions & exit /b 1 ) &:: REQUIRES command extensions for %cmdcmdline% and %~$PATH:1 syntax

call :_is_similar_command _FROM_CONSOLE "%COMSPEC%" %cmdcmdline%
if "%_PAUSE_NEEDED%"=="0" ( goto :_START )
if "%_PAUSE_NEEDED%"=="1" ( goto :_START )
set _PAUSE_NEEDED=0
if %_FROM_CONSOLE% equ 0 ( set _PAUSE_NEEDED=1 )
goto :_START
::
:_is_similar_command VARNAME FILENAME1 FILENAME2
:: NOTE: not _is_SAME_command; that would entail parsing PATHEXT and concatenating each EXT for any argument with a NULL extension
setlocal
set _RETVAL=0
:: more than 3 ARGS implies %cmdcmdline% has multiple parts (therefore, NOT direct console execution)
if NOT [%4]==[] ( goto :_is_similar_command_RETURN )
:: deal with NULL extensions (if both NULL, leave alone; otherwise, use the non-NULL extension for both)
set _EXT_2=%~x2
set _EXT_3=%~x3
if NOT "%_EXT_2%"=="%_EXT_3%" if "%_EXT_2%"=="" (
    call :_is_similar_command _RETVAL "%~2%_EXT_3%" "%~3"
    goto :_is_similar_command_RETURN
    )
if NOT "%_EXT_2%"=="%_EXT_3%" if "%_EXT_3%"=="" (
    call :_is_similar_command _RETVAL "%~2" "%~3%_EXT_2%"
    goto :_is_similar_command_RETURN
    )
::if /i "%~f2"=="%~f3" ( set _RETVAL=1 )  &:: FAILS for shells executed with non-fully qualified paths (eg, subshells called with 'cmd.exe' or 'tcc')
if /i "%~$PATH:2"=="%~$PATH:3" ( set _RETVAL=1 )
:_is_similar_command_RETURN
endlocal & set "%~1=%_RETVAL%"
goto :EOF
::

:_START

if %_FROM_CONSOLE% EQU 1 (
    echo EXEC directly from command line
  ) else (
    echo EXEC indirectly [from explorer, dopus, perl system call, cmd /c COMMAND, subshell with switches/ARGS, ...]
    )
if %_PAUSE_NEEDED% EQU 1 ( pause )

Сначала я использовал if /i "%~f2"=="%~f3" в подпрограмме _is_similar_command. Изменение на if /i "%~$PATH:2"=="%~$PATH:3" и дополнительная проверка кода для расширений NULL позволяет коду работать для оболочек/подоболочек, открытых с помощью не полностью определенных путей (например, подоболочек, называемых только "cmd.exe" или "tcc" ).

Для аргументов без расширений этот код не анализирует и не использует расширения из% PATHEXT%. Он по существу игнорирует иерархию расширений, которые использует CMD.exe при поиске команды без расширения (первая попытка FOO.com, затем FOO.exe, затем FOO.bat и т.д.). Таким образом, _is_similar_command проверяет сходство, а не эквивалентность, между двумя аргументами как командами оболочки. Это может быть источником путаницы/ошибки, но, по всей вероятности, никогда не будет возникать на практике для этого приложения.

Изменить: Исходный код был старой. Код теперь обновляется до последней версии, которая имеет: (1) замененный %COMSPEC% и %cmdcmdline% в первом вызове, (2) добавила проверку для нескольких аргументов %cmdcmdline%, (3) эхо-сообщения больше (4) добавлена ​​новая переменная %_PAUSE_NEEDED%.

Следует отметить, что %_FROM_CONSOLE% устанавливается на основе конкретно того, был ли командный файл исключен непосредственно из командной строки консоли или косвенно через проводник или какие-либо другие средства. Эти "другие средства" могут включать в себя вызов perl system() или выполнение команды, например cmd /c COMMAND.

Добавлена ​​переменная %_PAUSE_NEEDED%, так что процессы (такие как perl), которые выполняют командный файл косвенно, могут обойти паузы в пакетном файле. Это было бы важно в случаях, когда вывод не передается на видимую консоль (например, perl -e "$o = qx{COMMAND}"). Если в таком случае происходит пауза, нажмите "Нажмите любую клавишу, чтобы продолжить". запрос на паузу никогда не будет отображаться пользователю, и процесс зависает в ожидании ввода неуправляемого пользователя. В случаях, когда взаимодействие с пользователем невозможно или не разрешено, переменную %_PAUSE_NEEDED% можно настроить на "0" или "1" (соответственно false или true). %_FROM_CONSOLE% по-прежнему правильно задан кодом, но значение %_PAUSE_NEEDED% в дальнейшем не устанавливается на основе %_FROM_CONSOLE%. Он просто прошел.

Также обратите внимание, что код будет неправильно распознавать выполнение как косвенное (%_FROM_CONSOLE%= 0) внутри подоболочки, если эта подоболочка будет открыта с помощью команды, содержащей ключи/опции (например, cmd /x). Как правило, это не большая проблема, так как подкровы обычно открываются без дополнительных переключателей, а %_PAUSE_NEEDED% может быть установлено на 0. При необходимости.

Предостерегающий кодоскоп.

Ответ 6

@echo% CMDCMDLINE% | find/I "/c" > nul && пауза