2009-02-04 7 views
11

Mam skrypt wsadowy DOS, który wywołuje aplikację java, która współdziała z użytkownikiem za pośrednictwem interfejsu użytkownika konsoli. Dla dobra argumentacji, nazwijmy to runapp.bat i jego zawartość będzieCzy jest jakiś sposób w skrypcie wsadowym, aby konsola była otwarta tylko w przypadku wywołania z Menedżera systemu Windows?

java com.example.myApp 

Jeśli skrypt wsadowy jest wywoływany w konsoli, wszystko działa bez zarzutu. Jeśli jednak skrypt zostanie wywołany z Menedżera okien, nowo otwarta konsola zostanie zamknięta zaraz po zakończeniu wykonywania aplikacji. Chcę, aby konsola pozostała otwarta we wszystkich przypadkach.

wiem z poniższych sztuczek:

  • dodać polecenie pause na końcu skryptu. Jest to trochę brzydkie w przypadku, gdy runapp.bat zostanie wywołany z wiersza poleceń.

  • stworzyć nową powłokę za pomocą cmd /K java com.example.myApp Jest to najlepsze rozwiązanie znalazłem do tej pory, ale pozostawia dodatkowy środowiska powłoki przy wywołaniu z linii poleceń, tak że nazywając exit właściwie nie zamknąć powłokę.

Czy istnieje lepszy sposób?

Odpowiedz

12

Zobacz na to pytanie: Detecting how a batch file was executed

Ten skrypt nie zostanie wstrzymane, jeśli uruchomić z konsoli poleceń, ale jeśli dwukrotnym kliknięciu w Explorerze:

@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 
3

I wolą używać %cmdcmdline% jak napisali w komentarzu do odpowiedzi Patricka na inne pytanie (którego nie znalazłem, chociaż wyglądałem). W ten sposób, nawet jeśli ktoś zdecyduje się użyć cudzysłowów do wywołania skryptu wsadowego, nie wywoła to fałszywego pozytywu.

Moje ostateczne rozwiązanie:

@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 
0

ja często wykorzystują alternatywne formy (głównie TCC/LE z jpsoft.com) i podpowłok. Odkryłem, że ten kod działa dla szerszego, bardziej ogólnym przypadku (i nie wymaga 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) 

Początkowo używałem if /i "%~f2"=="%~f3" w _is_similar_command podprogramu. Zmiana na if /i "%~$PATH:2"=="%~$PATH:3" i dodatkowe sprawdzenie kodu dla rozszerzeń NULL pozwala kodowi działać dla powłok/podpowłok otwartych przy użyciu niekompletnych ścieżek (np. Podpowłoki wywoływane za pomocą "cmd.exe" lub "tcc").

Dla argumentów bez rozszerzeń ten kod nie analizuje i nie używa rozszerzeń z% PATHEXT%. Zasadniczo ignoruje hierarchię rozszerzeń używanych przez CMD.exe podczas wyszukiwania polecenia bez rozszerzenia (pierwsza próba FOO.com, następnie FOO.exe, następnie FOO.bat, itd.). Tak więc, _is_similar_command sprawdza podobieństwo, a nie równoważność między tymi dwoma argumentami, jako poleceniami powłoki. Może to być źródłem pomyłki/błędu, ale we wszystkich przypadkach nigdy nie powstanie jako problem w praktyce dla tej aplikacji.

Edytuj: Kod początkowy był starą wersją.Kod jest teraz zaktualizowany do najnowszej wersji, która ma: (1) zamieniony %COMSPEC% i %cmdcmdline% w pierwszym połączeniu, (2) dodał sprawdzanie dla wielu argumentów %cmdcmdline%, (3) echo wiadomości są bardziej szczegółowe o tym, co jest wykrywane, i (4) dodano nową zmienną %_PAUSE_NEEDED%.

Należy zauważyć, że ustawienie %_FROM_CONSOLE% jest ustalane w zależności od tego, czy plik wsadowy został wykonany bezpośrednio z wiersza poleceń konsoli, czy pośrednio za pomocą eksploratora lub w inny sposób. Te "inne środki" mogą obejmować wywołanie systemowe perl() lub wykonanie polecenia, takiego jak cmd /c COMMAND.

Zmodyfikowano zmienną %_PAUSE_NEEDED%, aby procesy (takie jak Perl), które pośrednio wykonują plik wsadowy, mogą ominąć przerwy w pliku wsadowym. Jest to ważne w przypadkach, w których sygnał wyjściowy nie jest podłączony do widocznej konsoli (np. perl -e "$o = qx{COMMAND}"). Jeśli w takim przypadku wystąpi pauza, "Naciśnij dowolny klawisz, aby kontynuować." monit o wstrzymanie nigdy nie zostanie wyświetlony użytkownikowi, a proces będzie zawieszony w oczekiwaniu na niepoprawne wprowadzenie danych przez użytkownika. W przypadkach, w których interakcja użytkownika nie jest możliwa lub niedozwolona, ​​zmienna %_PAUSE_NEEDED% może być ustawiona na "0" lub "1" (odpowiednio wartość false lub true). %_FROM_CONSOLE% jest nadal poprawnie ustawiony przez kod, ale wartość %_PAUSE_NEEDED% nie jest później ustawiana w oparciu o %_FROM_CONSOLE%. Po prostu przechodzi.

Należy również zauważyć, że kod błędnie wykryje wykonanie jako pośrednie (%_FROM_CONSOLE% = 0) w podpowłoce, jeśli podpięcie jest otwierane za pomocą polecenia zawierającego przełączniki/opcje (np. cmd /x). Zasadniczo nie stanowi to dużego problemu, ponieważ podpowłoki są zwykle otwierane bez dodatkowych przełączników, aw razie potrzeby można ustawić wartość 0 na 0.

Zastrzeżenie codor.

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

wykona zadanie. & wykona polecenie jeden po drugim. Jeśli użyjesz & &, możesz się zepsuć, jeśli się nie uda.

1

Uwzględnij tę linię w pliku wsadowym i dwukrotnie kliknąć na plik wsadowy w Explorer: „polecenia skryptów w tych cytatów oddzielonych & &”

cmd/k

Na przykład

cmd/k "cd ../ .. & & reż & & cd some_directory"

pełny zestaw opcji do cmd można znaleźć here

-2

@echo% CMDCMDLINE% | find/I "/ c"> nul & & pauza

+0

Czy mógłbyś wyjaśnić, jak to działa? –

Powiązane problemy