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

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

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

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

Ответ 1

Нашел один:-) - После отчаянного размышления о том, что 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. Он может или не может работать, ломаться, делать что-то странное, есть детей (может быть, хорошо) или укусить вас в носу.

Ответ 2

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

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

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

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

На простом английском языке это

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

Позже в script мы можем сделать:

if defined standalone pause

Ответ 3

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

@set nested=%nested%Z

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

-Oisin

Ответ 4

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

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

@echo %cmdcmdline%

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

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

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

Если я запустил "cmd.exe" , нажав "Start-Orb" и "Command Prompt" или щелкнув "Start-Orb" и выполнив "cmd.exe" из поля поиска/запуска. Затем я запускаю пакетный файл test.cmd, отображение эха% cmdcmdline% равно:

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

Кроме того, для меня, если я нажму "Командная строка" из ярлыка на рабочем столе, затем запустите пакетный файл test.cmd, отображение эха% cmdcmdline% также:

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

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

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

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