2009-02-04 29 views
11

Tôi có một tập lệnh batch DOS gọi một ứng dụng java tương tác với người dùng thông qua giao diện điều khiển giao diện người dùng. Vì lợi ích của đối số, chúng ta hãy gọi nó runapp.bat và nội dung của nó đượcCó cách nào trong tập lệnh batch để giữ bàn điều khiển mở chỉ khi được gọi từ Windows Manager?

java com.example.myApp 

Nếu kịch bản hàng loạt được gọi trong một giao diện điều khiển, tất cả mọi thứ hoạt động tốt. Tuy nhiên, nếu tập lệnh được gọi từ Trình quản lý cửa sổ, giao diện điều khiển mới mở sẽ đóng ngay sau khi ứng dụng hoàn tất việc thực thi. Điều tôi muốn là để bàn điều khiển luôn mở trong mọi trường hợp.

tôi biết các thủ thuật sau đây:

  • thêm một lệnh pause ở phần cuối của kịch bản. Đây là một chút xấu xí trong trường hợp runapp.bat được gọi từ dòng lệnh.

  • Tạo vỏ mới bằng cách sử dụng cmd /K java com.example.myApp Đây là giải pháp tốt nhất mà tôi đã tìm thấy cho đến nay, nhưng để lại môi trường vỏ ngoài khi được gọi từ dòng lệnh, để gọi exit không thực sự đóng trình bao.

Có cách nào tốt hơn không?

Trả lời

12

Xem câu hỏi này: Detecting how a batch file was executed

Kịch bản này sẽ không dừng lại nếu chạy từ lệnh console, nhưng sẽ nếu nhấn đúp chuột trong Explorer:

@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

Tôi thích sử dụng %cmdcmdline% như được đăng trong các bình luận với câu trả lời của Patrick cho câu hỏi khác (mà tôi không thấy mặc dù đã nhìn). Bằng cách đó, ngay cả khi ai đó quyết định sử dụng dấu ngoặc kép để gọi kịch bản lệnh, nó sẽ không kích hoạt dương tính giả.

giải pháp cuối cùng của tôi:

@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

tôi thường xuyên sử dụng vỏ thay thế (chủ yếu là TCC/LE từ jpsoft.com) và subshells. Tôi đã tìm thấy rằng mã này làm việc cho một trường hợp rộng hơn, tổng quát hơn (và nó không đòi hỏi 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) 

Ban đầu, tôi đã sử dụng if /i "%~f2"=="%~f3" trong _is_similar_command chương trình con. Thay đổi thành if /i "%~$PATH:2"=="%~$PATH:3" và kiểm tra mã bổ sung cho phần mở rộng NULL cho phép mã hoạt động đối với shell/subshells được mở với đường dẫn không đủ điều kiện (ví dụ: subshells được gọi với chỉ 'cmd.exe' hoặc 'tcc').

Đối với đối số không có tiện ích mở rộng, mã này không phân tích cú pháp và sử dụng tiện ích mở rộng từ% PATHEXT%. Về cơ bản nó bỏ qua thứ bậc của các phần mở rộng mà CMD.exe sử dụng khi tìm kiếm một lệnh không có phần mở rộng (đầu tiên thử FOO.com, sau đó là FOO.exe, sau đó là FOO.bat, v.v.). Vì vậy, _is_similar_command kiểm tra tính tương tự, không tương đương, giữa hai đối số dưới dạng lệnh trình bao. Điều này có thể là một nguồn của sự nhầm lẫn/lỗi, nhưng sẽ, trong tất cả các khả năng, không bao giờ phát sinh như là một vấn đề trong thực tế cho ứng dụng này.

Chỉnh sửa: Mã ban đầu là phiên bản cũ.Mã này hiện được cập nhật lên phiên bản mới nhất có: (1) hoán đổi %COMSPEC%%cmdcmdline% trong cuộc gọi ban đầu, (2) thêm séc cho nhiều đối số %cmdcmdline%, (3) thông điệp lặp lại cụ thể hơn về những gì được phát hiện, và (4) một biến mới %_PAUSE_NEEDED% đã được thêm vào.

Cần lưu ý rằng %_FROM_CONSOLE% được đặt cụ thể dựa vào việc tệp lô có được thực thi trực tiếp từ dòng lệnh của bàn điều khiển hoặc gián tiếp thông qua trình khám phá hoặc một số phương tiện khác. Những "phương tiện khác" có thể bao gồm một hệ thống perl() gọi hoặc bằng cách thực hiện một lệnh như cmd /c COMMAND.

Biến số %_PAUSE_NEEDED% được thêm vào để các quy trình (chẳng hạn như perl) thực thi tệp lô gián tiếp có thể bỏ qua tạm dừng trong tệp lô. Điều này sẽ rất quan trọng trong trường hợp đầu ra không được dẫn tới bảng điều khiển hiển thị (ví dụ: perl -e "$o = qx{COMMAND}"). Nếu tạm dừng xảy ra trong trường hợp này, "Nhấn phím bất kỳ để tiếp tục..." tạm dừng nhắc sẽ không bao giờ được hiển thị cho người dùng và quá trình sẽ treo chờ đợi cho đầu vào người dùng chưa từng có. Trong trường hợp tương tác của người dùng không thể hoặc không được phép, biến số %_PAUSE_NEEDED% có thể được đặt trước thành "0" hoặc "1" (sai hoặc đúng). %_FROM_CONSOLE% vẫn được đặt chính xác theo mã, nhưng giá trị của %_PAUSE_NEEDED% không được đặt sau đó dựa trên %_FROM_CONSOLE%. Nó chỉ đi qua. Và cũng lưu ý rằng mã sẽ phát hiện không chính xác như gián tiếp (%_FROM_CONSOLE% = 0) trong một vỏ con nếu vỏ đó được mở bằng lệnh có các công tắc (tùy chọn cmd /x). Nói chung đây không phải là vấn đề lớn vì subshells thường được mở mà không cần thêm công tắc và %_PAUSE_NEEDED% có thể được đặt thành 0, khi cần thiết.

Bộ mã hóa gọn gàng.

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

sẽ thực hiện công việc. & sẽ thực thi lệnh này đến lệnh khác. Nếu bạn sử dụng & & bạn có thể phá vỡ nếu một lỗi không thành công.

1

Bao gồm dòng này trong một tập tin thực thi và nhấp đúp chuột vào tập tin thực thi trong thám hiểm: "lệnh script trong các dấu ngoặc kép tách bởi & &"

cmd/k

Ví dụ

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

đầy đủ các tùy chọn để cmd có thể được tìm thấy here

-2

@echo% CMDCMDLINE% | find/I "/ c"> nul & & tạm dừng

+0

Bạn có giải thích cách hoạt động của tính năng này không? –

Các vấn đề liên quan