11

我有一个 DOS 批处理脚本,它调用一个通过控制台 UI 与用户交互的 java 应用程序。为了论证起见,我们称其为runapp.bat,其内容为

java com.example.myApp

如果在控制台中调用批处理脚本,一切正常。但是,如果从窗口管理器调用脚本,则新打开的控制台会在应用程序完成执行后立即关闭。我想要的是控制台在所有情况下都保持打开状态。

我知道以下技巧:

  • pause在脚本末尾添加命令。runapp.bat如果从命令行调用,这有点难看。

  • 创建一个新的 shellcmd /K java com.example.myApp这是我迄今为止找到的最好的解决方案,但是当从命令行调用时会留下一个额外的 shell 环境,因此调用exit实际上并不会关闭 shell。

有没有更好的办法?

4

6 回答 6

12

看到这个问题:Detecting how a batch file was executed

如果从命令控制台运行此脚本不会暂停,但如果在资源管理器中双击则会暂停:

@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
于 2009-02-04T12:02:44.100 回答
3

我更喜欢使用%cmdcmdline%评论中发布的内容,而不是帕特里克对另一个问题的回答(虽然看起来我没有找到)。这样,即使有人决定使用引号来调用批处理脚本,也不会触发误报。

我的最终解决方案:

@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
于 2009-02-04T19:57:42.563 回答
3
cmd /K java com.example.myApp & pause & exit

将完成这项工作。& 将一个接一个地执行命令。如果你使用 && 如果一个失败,你可以打破。

于 2009-06-10T15:59:10.977 回答
1

将此行包含在批处理文件中,然后在资源管理器中双击批处理文件:

cmd /k "这些引号内的脚本命令由 && 分隔"

例如

cmd /k "cd ../.. && 目录 && cd some_directory"

可以在此处找到 cmd 的完整选项

于 2010-12-04T18:27:22.760 回答
0

我经常使用备用外壳(主要是来自 jpsoft.com 的 TCC/LE)和子外壳。我发现这段代码适用于更广泛、更一般的情况(并且不需要 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子程序中使用过。对 NULL 扩展的更改if /i "%~$PATH:2"=="%~$PATH:3"和附加代码检查允许代码适用于以非完全限定路径打开的 shell/子shell(例如,仅使用“cmd.exe”或“tcc”调用的子shell)。

对于没有扩展名的参数,此代码不会解析和使用来自 %PATHEXT% 的扩展名。它基本上忽略了 CMD.exe 在搜索没有扩展名的命令时使用的扩展名的层次结构(首先尝试 FOO.com,然后是 FOO.exe,然后是 FOO.bat,等等)。因此,_is_similar_command检查两个参数之间的相似性,而不是等价性作为 shell 命令。这可能是混淆/错误的来源,但很可能在此应用程序的实践中不会出现问题。

编辑:初始代码是旧版本。代码现在更新到最新版本,它具有:(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”(分别为假或真)。%_FROM_CONSOLE%仍由代码正确设置,但 的值%_PAUSE_NEEDED%随后并未基于%_FROM_CONSOLE%. 它只是通过。

还要注意,%_FROM_CONSOLE%如果使用包含开关/选项(例如,)的命令打开子shell,代码将错误地检测到子shell 内的间接执行(=0 cmd /x)。通常这不是一个大问题,因为子shell 通常在没有额外开关的情况下打开,并且%_PAUSE_NEEDED%可以在必要时设置为 0。

警告编码。

于 2009-05-03T04:27:34.150 回答
-2

@echo %CMDCMDLINE% | 查找 /I " /c " >nul && 暂停

于 2014-04-17T20:47:10.847 回答