Есть ли способ в пакетной версии 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 && пауза