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.
Czy mógłbyś wyjaśnić, jak to działa? –