2009-02-04 3 views
11

J'ai un script batch DOS qui appelle une application Java qui interagit avec l'utilisateur via l'interface utilisateur de la console. Pour les besoins du raisonnement, nous allons l'appeler runapp.bat et son contenu soitY a-t-il un moyen dans un script batch de garder la console ouverte uniquement si elle est invoquée à partir de Windows Manager?

java com.example.myApp 

Si le script batch est appelé dans une console, tout fonctionne bien. Toutefois, si le script est appelé à partir du Gestionnaire de fenêtres, la console nouvellement ouverte se ferme dès que l'application a terminé l'exécution. Ce que je veux, c'est que la console reste ouverte dans tous les cas.

Je sais des trucs suivants:

  • ajouter une commande pause à la fin du script. C'est un peu moche dans le cas runapp.bat est invoqué à partir de la ligne de commande.

  • créer un nouveau shell en utilisant cmd /K java com.example.myApp Ceci est la meilleure solution que je trouve à ce jour, mais laisse un environnement shell supplémentaire lorsqu'elle est appelée à partir de la ligne de commande, de sorte que l'appel exit ne se ferme pas réellement la coquille.

Y a-t-il un meilleur moyen?

Répondre

12

Voir cette question: Detecting how a batch file was executed

Ce script ne sera pas une pause si elle est exécutée à partir de la console de commande, mais si un double-clic dans l'Explorateur:

@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

Je préfère utiliser %cmdcmdline% telle que publiée dans le commentaire à la réponse de Patrick à l'autre question (que je n'ai pas trouvée bien que regardé). De cette façon, même si quelqu'un décide d'utiliser des guillemets pour appeler le script batch, il ne déclenchera pas le faux positif.

Ma solution finale:

@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

J'utilise souvent des coquilles de rechange (principalement TCC/LE de jpsoft.com) et sous-couches. J'ai trouvé que ce code fonctionne pour une plus large, cas plus général (et il ne nécessite pas 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) 

Dans un premier temps, je l'avais utilisé if /i "%~f2"=="%~f3" dans le sous-programme _is_similar_command. La modification à if /i "%~$PATH:2"=="%~$PATH:3" et la vérification de code supplémentaire pour les extensions NULL permet au code de fonctionner pour les shells/sous-shell ouverts avec des chemins non qualifiés (par exemple, sous-shell appelés avec juste 'cmd.exe' ou 'tcc').

Pour les arguments sans extension, ce code n'analyse pas et n'utilise pas les extensions de% PATHEXT%. Il ignore essentiellement la hiérarchie des extensions que CMD.exe utilise lors de la recherche d'une commande sans extension (d'abord tenter FOO.com, puis FOO.exe, puis FOO.bat, etc.). Ainsi, _is_similar_command vérifie la similarité, et non l'équivalence, entre les deux arguments en tant que commandes shell. Cela pourrait être une source de confusion/erreur, mais ne se poserait probablement jamais comme un problème dans la pratique pour cette application.

Édition: Le code initial était une ancienne version.Le code est maintenant mis à jour à la version la plus récente qui a: (1) un échange %COMSPEC% et %cmdcmdline% dans l'appel initial, (2) a ajouté une vérification pour plusieurs arguments %cmdcmdline%, (3) les messages écho sont plus spécifiques sur ce qui est détecté, et (4) une nouvelle variable %_PAUSE_NEEDED% a été ajoutée.

Il est à noter que %_FROM_CONSOLE% est défini en fonction de l'exécution du fichier de commandes directement depuis la ligne de commande de la console ou indirectement via l'explorateur ou d'autres moyens. Ces "autres moyens" peuvent inclure un appel système perl() ou en exécutant une commande telle que cmd /c COMMAND.

La variable %_PAUSE_NEEDED% a été ajoutée afin que les processus (tels que perl) qui exécutent le fichier de commandes indirectement puissent ignorer les pauses dans le fichier de commandes. Cela serait important dans les cas où la sortie n'est pas transmise à la console visible (par exemple, perl -e "$o = qx{COMMAND}"). Si une pause se produit dans un tel cas, le message "Appuyez sur n'importe quelle touche pour continuer.". L'invite de pause ne s'affichera jamais pour l'utilisateur et le processus se bloquera en attente d'une entrée utilisateur non sollicitée. Dans les cas où l'interaction de l'utilisateur est impossible ou interdite, la variable %_PAUSE_NEEDED% peut être préréglée sur "0" ou "1" (false ou true, respectivement). %_FROM_CONSOLE% est toujours défini correctement par le code, mais la valeur de %_PAUSE_NEEDED% n'est pas définie par la suite en fonction de %_FROM_CONSOLE%. C'est juste passé.

Et notez également que le code détectera incorrectement l'exécution comme indirecte (%_FROM_CONSOLE% = 0) dans un sous-shell si ce sous-shell est ouvert avec une commande contenant des commutateurs/options (par exemple, cmd /x). Généralement ce n'est pas un gros problème car les sous-cases sont généralement ouvertes sans commutateurs supplémentaires et %_PAUSE_NEEDED% peut être réglé sur 0, si nécessaire.

Codeur de caveat.

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

fera le travail. Le & exécutera la commande l'un après l'autre. Si vous utilisez & & vous pouvez casser si l'un échoue.

1

Inclure cette ligne dans un fichier de commandes et double cliquez sur le fichier de commandes dans l'explorateur:

"commandes de script au sein de ces citations séparées par & &" cmd/k

Par exemple

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

Le Vous pouvez trouver un complément complet d'options à cmd. here

-2

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

+0

Pouvez-vous expliquer comment cela fonctionne? –

Questions connexes