Приостановка пакетного файла при двойном щелчке, но не при запуске из окна консоли? - PullRequest
24 голосов
/ 24 августа 2010

Есть ли способ для командного файла (в данном случае работающего в Windows XP) определить, был ли он запущен из командной строки (т.е. внутри окна консоли) или запущен через оболочку (например, двойным щелчком мыши)

У меня есть скрипт, который я хотел бы приостановить в определенные моменты при запуске через оболочку, но не при запуске из командной строки. Я видел похожий вопрос в отношении SO, но я не могу использовать одно и то же решение по двум причинам: во-первых, должна ли зависимость от паузы зависеть от нескольких факторов, только один из которых - был дважды нажат. Во-вторых, я буду распространять этот сценарий среди других членов моей команды, и я не могу реально попросить всех их внести изменения в реестр, которые повлияют на все сценарии.

Возможно ли это?

Ответы [ 4 ]

34 голосов
/ 24 августа 2010

Найден один :-) - После отчаянного размышления о том, что может сделать cmd при интерактивном запуске, а не при непосредственном запуске командного файла ... Я наконец нашел один.

Псевдопеременная %cmdcmdline% содержит командную строку, которая использовалась для запуска cmd. Если cmd был запущен нормально, в нем есть что-то похожее на:

"C:\Windows\System32\cmd.exe"

Однако при запуске командного файла это выглядит так:

cmd /c ""C:\Users\Me\test.cmd" "

Небольшая демонстрация:

@echo off
for %%x in (%cmdcmdline%) do if /i "%%~x"=="/c" set DOUBLECLICKED=1
if defined DOUBLECLICKED pause

Этот способ проверки может быть не самым надежным, но /c должен присутствовать только в качестве аргумента, если пакетный файл был запущен напрямую.

Работает на моей машине http://hypftier.de/dump/works_on_my_machine.png

Проверено здесь на Windows 7 x64. Это может или не может работать, ломаться, делать что-то странное, есть детей (может быть, хорошо) или кусать вас за нос.

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

Консолидированный ответ, полученный из большей части информации, найденной на этой странице (и некоторых других страницах переполнения стека с подобными вопросами). Этот не полагается на обнаружение / c, но фактически проверяет имя сценария в командной строке. В результате это решение не остановится, если дважды щелкнуть другой пакет, а затем вызвать его; Вы должны были дважды щелкнуть по этому пакетному файлу.

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

Редактировать: то же самое можно сделать в одной строке:

echo %cmdcmdline% | findstr /i /c:"%~nx0" && set standalone=1

На простом английском это

  • передает значение от %cmdcmdline% до findstr , которое затем ищет текущее имя сценария
  • %0 содержит текущее имя сценария, конечно, только если shift не был вызван заранее
  • %~nx0 извлекает имя и расширение файла из %0
  • >NUL 2>&1 отключение звука findstr путем перенаправления любого вывода в NUL
  • findstr устанавливает ненулевой уровень ошибки, если не удается найти подстроку в вопросе
  • && выполняется только в том случае, если предыдущая команда вернулась без ошибки
  • как следствие, standalone не будет определено, если скрипт был запущен из командной строки

Позже в скрипте мы можем сделать:

if defined standalone pause
2 голосов
/ 24 августа 2010

Одним из подходов может быть создание файла autoexec.nt в корне c: \, который будет выглядеть примерно так:

@set nested=%nested%Z

В вашем пакетном файле проверьте, является ли% nested% "Z" - если это "Z", то вы дважды щелкнули, поэтому сделайте паузу. Если это не «Z» - это будет «ZZ» или «ZZZ» и т. Д., Поскольку CMD наследует блок среды родительского процесса.

-Oisin

0 голосов
/ 20 августа 2012

Немного больше информации ...

Я начинаю с пакетного файла (test.cmd), который содержит:

@echo %cmdcmdline%

Если я дважды щелкну "test.cmd"«пакетный файл из Windows Explorer, отображение echo% cmdcmdline%:

cmd /c ""D:\Path\test.cmd" "

При выполнении пакетного файла« test.cmd »из окна командной строки отображается
echo% cmdcmdline% зависит от того, как было запущено командное окно ...

Если я запускаю «cmd.exe», нажимая «Start-Orb» и «Командная строка», или если я нажимаю «Start-Orb "и выполните" cmd.exe "из окна поиска / запуска.Затем я запускаю пакетный файл «test.cmd», отображение echo% cmdcmdline%:

"C:\Windows\system32\cmd.exe"

Кроме того, для меня, если я нажимаю «Командная строка» в ярлыке на рабочем столе, затем выполняюпакетный файл "test.cmd", отображение echo% cmdcmdline% также:

"C:\Windows\system32\cmd.exe"

Но если я щелкну правой кнопкой мыши внутри окна Windows Explorer и выберу "Открыть командную строку здесь"", затем выполните командный файл" test.cmd ", отображение echo% cmdcmdline%:

"C:\Windows\System32\cmd.exe" /k ver

Так что будьте осторожны, если вы запускаете" cmd.exe "из ярлыка, которыйсодержит "/ c" в поле "Target" (маловероятно), тогда тест в предыдущем примере не сможет правильно проверить этот случай.

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