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%
và %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.
Bạn có giải thích cách hoạt động của tính năng này không? –