Как заставить Windows приостановить пакетный файл при двойном щелчке? - PullRequest
7 голосов
/ 20 мая 2009

Я написал командный файл для автоматизации некоторых задач. Я могу запустить его из командной строки, и он запускается и отображает результаты. Если я дважды щелкну по нему из проводника, он запустится и немедленно прекратит работу, поэтому я не смогу увидеть результаты.

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

Мне не нужно передавать параметр / nopause или что-то еще, когда я вызываю командный файл из командной строки. Я хотел бы найти решение, в котором я могу использовать командный файл, не делая ничего особенного?

Спасибо.

ПРИМЕЧАНИЕ Я не хочу, чтобы он останавливался при запуске из командной строки !! Я могу вызвать этот пакетный файл из другого пакетного файла для выполнения загрузки операций. В этом случае я не могу сидеть там, чтобы продолжать вводить.

В идеале было бы лучше, если бы я мог поместить некоторый код в пакетный файл, чтобы он мог определить, откуда он был запущен, а затем сделать паузу или нет, если это необходимо.

Ответы [ 7 ]

14 голосов
/ 20 мая 2009

Использование:

cmd /K myBatch.bat

как ваш ярлык.

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

Вот решение, которое должно работать хорошо и учитывать вероятность того, что пакетный файл может вызвать другой пакетный файл («вложенный»).

Вы можете использовать Find для поиска «/ c», которого не должно быть, если пакетный файл запускается из «Командной строки»:

echo %cmdcmdline% | find /i "/c"

Но вы могли бы сделать более «надежный» тест, используя Find для поиска более длинной строки или имени пакетного файла.

Команда "Найти" не будет работать должным образом, если в строке поиска есть (") двойные кавычки. Чтобы обойти это, вы можете использовать подстановку переменных среды, чтобы" скорректировать "строку, чтобы она хорошо работала с Find:

set newcmdcmdline=%cmdcmdline:"=-%

Обычно возвращается:

if the batch-file is run from a "Command Prompt"  
    newcmdcmdline=-C:\Windows\system32\cmd.exe-

if the batch-file is run by clicking on the the batch-file  
(or the batch-file shortcut) from "Windows Explorer"  
    newcmdcmdline=cmd /c --D:\Path\test.cmd- -

Затем вы можете использовать «Найти» для проверки, как:

    echo %newcmdcmdline% | find /i "cmd /c --"
or
    echo %newcmdcmdline% | find /i "cmd /c --%~dpf0%-"

Далее вам нужно решить, хотите ли вы, чтобы «вложенный» пакетный файл вел себя так, как если бы вы выполняли его так же, как вызывающий пакетный файл, или вы хотите, чтобы вложенные пакетные файлы всегда вели себя так, как если бы они были выполнены из «командной строки».

Учтите, что если вы работаете во вложенном пакетном файле, то проверьте это:

echo %newcmdcmdline% | find /i "cmd /c --%~dpf0%-"

всегда завершится ошибкой (без совпадения), поскольку% newcmdcmdline% содержит имя самого внешнего пакетного файла, а не вложенный пакетный файл.

Таким образом, первое решение будет вести себя одинаково для вызывающего пакетного файла и всех вложенных пакетных файлов. Также отлично подходит, если вы не вызываете пакетные файлы:

Во всех пакетных файлах (вызывающих и вложенных), которые вы хотите выполнить в этом тесте, добавьте эти строки, обычно в верхней части пакетных файлов (вы можете исключить операторы echo, если хотите):

if not defined withincmd call :testshell
if %withincmd% EQU 0 echo This batch-file: %~dpf0 was executed directly (from Windows Explorer, ...).
if %withincmd% EQU 1 echo This batch-file: %~dpf0 was executed from within a Command Prompt
rem if %withincmd% EQU 0 pause

Затем, где-нибудь внутри каждого пакетного файла, добавьте подфункцию testshell:

goto :EOF
:testshell
rem "Nested" batch-files won't see this because withincmd is already defined
if not defined newcmdcmdline set newcmdcmdline=%cmdcmdline:"=-%
set withincmd=1
echo %newcmdcmdline% | find /i "cmd /c --%~dpf0%-"
if %errorlevel% EQU 0 set withincmd=0
goto :EOF

Вы можете сделать условный вызов «testhell» только один раз, вверху самого внешнего пакетного файла.

В некоторых ситуациях может потребоваться, чтобы только «самый внешний» пакетный файл вел себя по-другому, если он выполняется из «командной строки», и если он запускается нажатием на пакетный файл (или пакетный ярлык файла) из "Проводника Windows". Таким образом, пакетные файлы, вызываемые из «самого внешнего» пакетного файла, всегда будут вести себя одинаково независимо от того, как они выполняются.

Чтобы это работало, у вас есть несколько вариантов.

1) Сохраните значение «insidecmd» перед вызовом другого пакетного файла и восстановите предыдущее значение «insidecmd» после возврата вызванного пакетного файла. Это немного сложно для большинства случаев.

2) Используйте «глобально уникальное» имя переменной для «withincmd» в каждом пакетном файле.

3) Выполняйте команду «Найти» каждый раз, когда вам нужно узнать, как был запущен текущий пакетный файл.

4) Увеличивать переменную при входе в пакетный файл и уменьшать ее при выходе из пакетного файла, а затем проверять только, как запускался пакетный файл, если count-variable = 1

Метод 3 является самым простым, но имеет недостаток в том, что если самый внешний пакетный файл вызывается из самого себя (как в рекурсии) или из другого пакетного файла, тестовая переменная (в пределах cmd) не будет правильно установлена.

Вот как это сделать, используя метод 3:

Во все пакетные файлы (вызывающие и вложенные), которые вы хотите выполнить в этом тесте, добавьте эти строки, как правило, в верхней части пакетных файлов (вы можете исключить операторы echo, если хотите):

call :testshell
if %withincmd% EQU 0 echo This batch-file: %~dpf0 was executed directly (from Windows Explorer, ...).
if %withincmd% EQU 1 echo This batch-file: %~dpf0 was executed from (or Nested) within a Command Prompt
rem if %withincmd% EQU 0 pause

Затем, где-нибудь внутри каждого пакетного файла, добавьте подфункцию testshell:

goto :EOF
:testshell
if not defined newcmdcmdline set newcmdcmdline=%cmdcmdline:"=-%
set withincmd=1
echo %newcmdcmdline% | find /i "cmd /c --%~dpf0%-"
if %errorlevel% EQU 0 set withincmd=0
goto :EOF

В этом случае вам придется вызывать «тестовую оболочку» один раз, вверху каждого пакетного файла, затем снова после того, как вы вернулись из вызова другого пакетного файла (или вызывать «тестовую оболочку» каждый раз, когда вам нужно знать как был запущен текущий пакетный файл).

Вот как это сделать, используя метод 4:

Во всех пакетных файлах (вызывающих и вложенных), которые вы хотите выполнить в этом тесте, добавьте эти строки, обычно в верхней части пакетных файлов (вы можете исключить операторы echo, если хотите):

if not defined nestinglevel set nestinglevel=0
set /A nestinglevel=nestinglevel+1
call :testshell
if %withincmd% EQU 0 echo This batch-file: %~dpf0 was executed directly (from Windows Explorer, ...).
if %withincmd% EQU 1 echo This batch-file: %~dpf0 was executed from (or Nested) within a Command Prompt
rem if %withincmd% EQU 0 pause

Затем, где-нибудь внутри каждого пакетного файла, добавьте подфункцию testshell:

goto :EOF
:testshell
if not defined newcmdcmdline set newcmdcmdline=%cmdcmdline:"=-%
set withincmd=1
if %nestinglevel% GEQ 2 goto :EOF
echo %newcmdcmdline% | find /i "cmd /c --%~dpf0%-"
if %errorlevel% EQU 0 set withincmd=0
goto :EOF

Кроме того, не забудьте уменьшить значение переменной при выходе из одного пакетного файла, чтобы вернуться к вызывающему пакетному файлу:

set /A nestinglevel=nestinglevel-1

В этом случае вам придется вызывать «testhell» один раз, вверху каждого пакетного файла, а затем снова после того, как вы вернулись из вызова другого пакетного файла (или вызывать «testhell» каждый раз, когда вам нужно знать как был запущен текущий пакетный файл).

Во всех случаях тестируйте% withincmd%, чтобы определить, как был запущен текущий пакетный файл, например:

if %withincmd% EQU 0 pause
if %withincmd% EQU 1 goto :EOF
3 голосов
/ 20 мая 2009

в конце файла печати

pause

будет ждать ввода любого ключа

1 голос
/ 16 апреля 2016

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

if "%parent%"=="" set parent=%~0
if "%console_mode%"=="" (set console_mode=1& for %%x in (%cmdcmdline%) do if /i "%%~x"=="/c" set console_mode=0)

и затем в конце

if "%parent%"=="%~0" ( if "%console_mode%"=="0" pause )

Он обрабатывает вложенные пакетные вызовы, когда вы хотите сделать паузу только в конце исходного пакетного файла, а не во вложенных пакетных файлах. Во вложенном пакетном файле %parent% уже установлен на исходный вызывающий объект, поэтому он не будет равняться вложенному %~0. Если у вас есть bat1, который вызывает bat2, он оставляет открытой возможность двойного щелчка в bat2 в Проводнике - в этом контексте bat2 остановится в конце, тогда как если bat1 вызывает bat2, то bat2 выиграно не делайте паузу в конце (только bat1 сделает паузу).

Разделитель операторов & помогает избежать визуального беспорядка для чего-то, что является вторичным по отношению к основной функции. Если вам не нравится его внешний вид, просто поместите каждое утверждение в новую строку.

Этот подход ищет /C в качестве одного из параметров в команде запуска (%cmdcmdline%). Предполагается, что ваши командные файлы не используют опцию /C. Если вы используете /C самостоятельно, вам нужно вместо этого проверить, появляется ли %COMSPEC% в пределах %cmdcmdline% (используйте FINDSTR). Когда Explorer запускает файл bat, его %cmdcmdline% включает %COMSPEC% например C:\Windows\System32\cmd.exe /C double_clicked_batch_file_name. В командном окне %cmdcmdline% просто содержит cmd.exe (без пути). Я использую CALL mybat вместо cmd.exe /C mybat, но вам, возможно, придется работать с существующими пакетными файлами.

0 голосов
/ 20 мая 2009

Вы можете просто добавить параметры в пакетный вызов и обработать оператор условной паузы в вашем пакете. Таким образом, при запуске из командной строки или dblclick пакет может приостановиться, когда вызовы из других пакетов с параметром / nopause не приостанавливаются.

0 голосов
/ 20 мая 2009

Будет ли работать команда паузы?

Документация Microsoft по паузе

0 голосов
/ 20 мая 2009

используйте «pause» в пакетном файле в конце, и он будет ждать ввода пользователя

НТН

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