Определить, запущен ли bat-файл двойным щелчком или из окна cmd - PullRequest
26 голосов
/ 02 мая 2011

У меня есть bat-файл, который делает кучу вещей и закрывает окно cmd, что нормально, когда пользователь дважды щелкает бат-файл в проводнике. Но если я запускаю файл bat из уже открытого окна cmd, как в cmd> c: \ myfile.bat, тогда я не хочу, чтобы файл bat закрывал окно cmd (END), поскольку мне нужно заняться другими делами. Мне нужен код команды bat dos, который будет делать что-то вроде

if (initiated_from_explorer) then
else
endif

Возможно ли это? спасибо

Ответы [ 10 ]

14 голосов
/ 29 августа 2013

Решение от "Мусио" приятно;однако мне лично не удалось заставить его работать в выражении «IF» из-за двойных кавычек в значении %cmdcmdline% (с или без двойных кавычек около %cmdcmdline%).

ОднакоРешение с использованием %0 работает нормально.Я использовал следующий оператор блока, и он работает как талисман:

IF %0 == "%~0"  pause

Следующее решение может также работать, если предыдущее не сработало (любезно предоставлено Алексом Эссильфи):

IF %0 EQU "%~dpnx0" PAUSE

Надеждаэто может помочь.

14 голосов
/ 02 мая 2011

%cmdcmdline% дает точную командную строку, используемую для запуска текущего Cmd.exe.

  • При запуске из командной консоли эта переменная равна "%SystemRoot%\system32\cmd.exe".
  • При запуске из проводника эта переменная cmd /c ""{full_path_to_the_bat_file}" ";
    это подразумевает, что вы также можете проверить переменную %0 в вашем файле bat, для в этом случае это всегда полный путь к файлу bat и всегда заключенный в двойные кавычки.

Лично я бы пошел на подход %cmdcmdline% (не %O), но учтите, что обе команды запуска могут быть переопределены в реестре ...

6 голосов
/ 26 февраля 2015

Сводный ответ, основанный на большей части информации, найденной на этой странице:

:pauseIfDoubleClicked
setlocal enabledelayedexpansion
set testl=%cmdcmdline:"=%
set testr=!testl:%~nx0=!
if not "%testl%" == "%testr%" pause
  1. Переменная «testl» получает полную строку вызова процессора cmd (согласно mousio), удаляя все надоедливые двойные кавычки.
  2. Переменная «testr» принимает «testl» и дополнительно удаляет имя текущего файла пакетного файла, если оно присутствует (что будет, если пакетный файл был вызван двойным щелчком).
  3. Оператор if определяет, различаются ли «testl» и «testr». Если да, партия была дважды нажата, поэтому сделайте паузу; если нет, пакет был введен в командной строке, продолжайте.

Естественно, если вы хотите сделать что-то еще, если обнаружите двойной щелчок, вы можете изменить паузу.

Спасибо всем.

3 голосов
/ 06 июня 2012

Используйте exit /b 0, а не exit

Первый будет завершен полностью, если запущен из Windows Explorer, но вернется в консоль, если запущен из командной строки.

3 голосов
/ 02 мая 2011

Вы можете добавить параметр командной строки при запуске из окна CMD, которое не существует при двойном щелчке файла. Если параметров нет, закройте окно. Если есть, не закрывайте его. Вы можете проверить параметр, используя %1

2 голосов
/ 02 мая 2011

Это не только возможно, но ваше желаемое поведение - это нормальное поведение выполнения пакетного файла, если вы не сделаете что-то «особенное»:

  • при выполнении пакетного файла с помощьюесли дважды щелкнуть его в проводнике, окно cmd закроется, когда оно будет сделано;
  • когда пакетный файл выполняется из командной строки, он просто возвращается в командную строку после завершения - окно не закрывается;

Так что я думаю, что вопрос нуждается вна что нужно ответить, что вы делаете в командном файле, который заставляет командное окно закрываться при выполнении его из командной строки?

1 голос
/ 19 декабря 2014

Как и @anishsane, я тоже хотел, чтобы оператор паузы запускался из проводника, но не при запуске из окна командной строки.

Вот что сработало для меня, основываясь на ответе @ mousio выше:

@SET cmdcmdline|FINDSTR /b "cmdcmdline="|FINDSTR /i pushd >nul
@IF ERRORLEVEL 1 (
    @echo.
    @echo Press ENTER when done
    @pause > nul
)

(Здесь нет ничего оригинального, только рабочий пример)

0 голосов
/ 21 мая 2018

после прочтения предложений, это то, что я пошел с:

set __cmdcmdline=%cmdcmdline%
set __cmdcmdline=%__cmdcmdline:"=%
set __cmdcmdline=%__cmdcmdline: =%
set __cmdcmdline=%__cmdcmdline:~0,5%
if "%__cmdcmdline%"=="cmd/c" set CMD_INITIATED_FROM_EXPLORER=1
set __cmdcmdline=

, которая условно устанавливает переменную: CMD_INITIATED_FROM_EXPLORER

.. и впоследствии может использоваться при необходимости:

if defined CMD_INITIATED_FROM_EXPLORER (
  echo.
  pause
)

.. но проблема, связанная с Powershell, о которой @ Ruben Bartelink упоминает, не решена:

работает ./batch.cmd от Powershell использует cmd /c под капотом

0 голосов
/ 17 мая 2017

@ dlchambers был близок, но набор не работал, так как cmdcmdline не является определенной переменной среды в некоторых случаях, но эта версия, основанная на его работах, отлично подходит для меня:

echo %cmdcmdline% | findstr /i pushd >nul
if errorlevel 1 pause
0 голосов
/ 16 ноября 2013

Вставьте это в начало скрипта BAT или CMD и, возможно, измените то, что происходит в предложении if:

:: To leave command window open if script run from Windows explorer.
@setlocal
@set x=%cmdcmdline:"=%
@set x=%x: =%
@set y=%x:cmd/c=%
@if "%x%" neq "%y%" cmd /k %0 %* && exit || exit
@endlocal

Что это делает, если пользователь дважды щелкнет или вызовет этот скрипт с помощью «cmd / c», он перезапустится с «cmd / k», который оставит сеанс открытым после завершения команды. Это позволяет пользователю выйти или, возможно, сделать что-то еще.

Причина, по которой вы делаете это таким образом, а не другими способами, объясненными в этом ответе, состоит в том, что я обнаружил ситуации, в которых все еще даже при использовании кавычек или других символов оператор IF будет срываться с определенными ситуациями КВ и / с и с пробелами. Таким образом, логика сначала удаляет все цитаты, а затем удаляет все пробелы .. потому что в некоторых случаях после удаления кавычек появляется дополнительный пробел.

set x=%cmdcmdline:"=%       <-- removes all quotes
set x=%x: =%                <-- removes all spaces
set y=%x:cmd/c=%            <-- removes  cmd/c  from the string saving it to  y

Точка выхода && || Выход таков, что если ERRORLEVEL перед выходом равен 0 (успех), он затем прекращает работу, но также, если он не равен 0 (некоторый сбой), он также прекращает работу.

Но вы можете заменить эту часть:

cmd /k %0 %* && exit || exit

с чем-то вроде

set CALLED_WITH_CMD_C=YES

, а затем придумайте свои отличия в остальной части вашего сценария. Затем вам нужно будет переместить или удалить эндокалл.

Символ '@' спереди просто предотвращает эхо, которое вы можете получить, если хотите протестировать. Не используйте echo on или echo off, поскольку это меняет настройку и влияет на все последующие сценарии, которые вызывают ваш.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...