Вопрос или проблема
В cmd, когда мы нажимаем Ctrl+C, целевое приложение завершает работу, но если приложение вызвано из пакетного файла, появляется подтверждение “Terminate batch job (Y/N)”. Я никогда не помню случая, когда я выбрал бы не завершать работу пакетного файла. Как можно пропустить это подтверждение?
Насколько я знаю, это невозможно, так как это поведение является частью дизайна и контролируется интерпретатором команд. Единственный способ “перехвата” или “переназначения” этого – декомпиляция и повторная компиляция самого интерпретатора.
На этом сайте я нашел эффективное решение:
script2.cmd < nul
Чтобы не набирать это каждый раз, я создал второй скрипт под названием script.cmd
в той же папке с указанной выше строкой. Я тестировал этот метод только на XP, но другие подтвердили его на Win 7.
Натан добавляет: другой вариант – добавить следующий код в начало script.cmd, который выполняет то же самое в одном файле:
rem Bypass "Terminate Batch Job" prompt.
if "%~1"=="-FIXED_CTRL_C" (
REM Remove the -FIXED_CTRL_C parameter
SHIFT
) ELSE (
REM Run the batch with <NUL and -FIXED_CTRL_C
CALL <NUL %0 -FIXED_CTRL_C %*
GOTO :EOF
)
Нажмите Ctrl+C дважды.
Установите Clink и измените параметр terminate_autoanswer настройки, выполнив на вашем приглашении:
clink set cmd.auto_answer answer_yes
Значение | Значение |
---|---|
off | Отключает автоматический ответ |
answer_yes | Отвечает ‘Y’ при запросе после Ctrl+C |
answer_no | Отвечает ‘N’ при запросе после Ctrl+C |
Альтернативно, в старых версиях clink, это можно сделать через файл настроек, который должен быть здесь: C:\Users\<username>\AppData\Local\clink\settings
.
# name: Auto-answer terminate prompt
# type: enum
# Automatically answers cmd.exe's 'Terminate batch job (Y/N)?' prompts. 0 =
# disabled, 1 = answer 'Y', 2 = answer 'N'.
terminate_autoanswer = 1
Теперь это “просто работает” с любым окном cmd.exe
. Вам не нужно изменять то, что выполняется, поскольку clink использует возможности cmd.exe
.
1
Просто невероятно, на мой скромный взгляд!
1 Однако вам потребуется закрыть и открыть заново cmd.exe
, прежде чем это
вступит в силу.
2 Оригинальный незаброшенный репозиторий Clink здесь: http://mridgers.github.io/clink/
Если вам не нужно делать что-либо в пакетном файле после того, как ваше приложение нормально завершилось, то использование команды start
гарантирует, что пакетный файл уже будет завершен к тому моменту, когда вы нажмете Ctrl-C. Поэтому сообщение не появится.
Например:
@echo off set my_command=ping.exe set my_params=-t www.google.com echo Command to be executed by 'start': %my_command% %my_params% :: Когда НЕ используется /B или /WAIT, это создаст новое окно, в то время как :: выполнение этого самого пакетного файла продолжится в текущем окне: start %my_command% %my_params% echo. echo Эта строка будет выполнена ПЕРЕД тем, как 'start' даже закончится. Поэтому этот echo пакетный файл завершится ДО того, как один из пользователей нажмет Ctrl-C в другом окне. echo. :: Для тестирования используйте 'pause', чтобы показать "Press any key to continue", чтобы увидеть :: вывод команд 'echo'. Убедитесь, что нажимаете Ctrl-C в окне, :: которое выполняет команду 'ping' (не в этом самом окне). Или просто уберите :: следующую строку при отсутствии понимания: pause
(Протестировано на Windows XP.)
Я долго боролся с желанием избежать подтверждения “Terminate batch job”.
Мое последнее озарение – это своего рода фокус (или консольное окно), заменяя один экземпляр cmd.exe
другим. Это достигается путем выполнения команды/программы через start cmd /k
, сразу после чего идет exit
в файле .BAT
.
Оригинальное консольное окно исчезает, а новое можно чисто остановить с помощью Ctrl–C.
Рассмотрим следующий пример traceroute
, который можно прервать с помощью Ctrl+C или разрешить ему завершиться, вернув пользователя к C:\>
приглашению:
@echo off
set timeout=100
if not "%2"=="" set timeout=%2
start cmd /k tracert -w %timeout% %1
exit
Замена среды нового командного интерпретатора может не подойти для всех, но, на взгляд непосвященного, это работает и выглядит вполне хорошо для меня.
Решение Gringo хорошее, но плохо работает со скриптами, которые передают список аргументов (например, python myscript.py %*
), поскольку SHIFT
не обновляет %*
. Существуют обходные пути, но у них есть определенные ограничения.
Вот модификация, к которой я пришел:
IF [%JUSTTERMINATE%] == [OKAY] (
SET JUSTTERMINATE=
python myscript.py %*
) ELSE (
SET JUSTTERMINATE=OKAY
CALL %0 %* <NUL
)
На 99.(9)% безупречно.
TCC/LE, который является бесплатной заменой для CMD (подумайте об этом как CMD++), имеет опцию для подавления запроса на завершение работы пакетного задания. Можно найти опцию в TCC Startup Configuration Dialog:
Отменить файлы пакетов по Ctrl-C: Отмените обработку пакетов без обычного запроса при нажатии Control-C.
Скриншот:
Если вы никогда не слышали о TCC/LE ранее, вот некоторые сведения с сайта:
TCC/LE – это замена для командной строки CMD (стандартный командный интерпретатор Windows). TCC/LE является надмножеством CMD, с 111 внутренними командами (CMD имеет меньше чем 40), 240 внутренними переменными и функциями, и сотнями усовершенствований для существующих команд CMD.
TCC/LE работает с вашими существующими приложениями командной строки и пакетными файлами, но предлагает значительные улучшения в возможностях командной строки и пакетных файлов, и добавляет тысячи новых функций к вашим окнам командной строки.
Я использовал TCC/LE в течение многих лет и 4NT до него. У меня очень хорошие чувства к нему, и я могу его рекомендовать. Единственная причина, по которой я больше его не использую, это то, что я почти исключительно использую PowerShell теперь.
Смотрите этот вопрос на Stack Overflow.
Однако патчить cmd.exe – это не то, что я стал бы делать ради этого.
Решение с использованием AutoHotkey
-
Скачайте и установите AutoHotkey
-
Создайте скрипт (например,
terminate.ahk
) -
Вставьте следующий скрипт
#SingleInstance Force
#IfWinActive ahk_exe cmd.exe
^d::terminate()
#IfWinActive ahk_exe powershell.exe
^d::terminate()
terminate()
{
SendInput {Ctrl down}c{Ctrl up}
Sleep 100
SendInput y{Enter}
}
- Выполните скрипт
Теперь, когда вы нажимаете Ctrl+D в powershell.exe
или cmd.exe
, отправляется последовательность Ctrl+C y Enter и это завершает выполнение программы.
Если вы хотите настроить горячую клавишу, смотрите Список клавиш
Если вы хотите применить эту горячую клавишу к другой программе, просто добавьте это в скрипт (например, Visual Studio Code
-> code.exe
):
#IfWinActive ahk_exe code.exe
^d::terminate()
Имя программы можно найти в Диспетчере задач > Детали
Самый простой способ подавить подтверждение, если вы используете терминал Hyper, это добавить плагин hyper-yes.
Я не знаю ваш контекст. Было бы очень полезно, если бы вы могли сказать, как вы запускаете приложение (используя start
или напрямую указав путь). Если вы можете перевести пакетный скрипт в один PowerShell скрипт, то pwsh -f script_file
может помочь вам.
Я прочитал этот QA, когда пытался использовать msys2
в терминале Windows. В терминале Windows мы можем использовать pwsh -c "$env:MSYSTEM='UCRT64';$env:CHERE_INVOKING='enabled_from_arguments';D:\msys64\usr\bin\bash -l"
, чтобы функционировать как D:\msys64\msys2_shell.cmd -defterm -here -no-start -ucrt64 -shell bash
(эта трансляция требует немного чтения пакетного скрипта). Таким образом, нам больше не нужен пакетный скрипт.
Обратите внимание, что мы не используем -NoExit
для pwsh
, который является одним из стандартных параметров для “Developer PowerShell for VS 2022” в терминале Windows, так что я думаю, что может быть также аналогичный параметр для start
, который используется msys2_shell.cmd
, когда не используется -no-start
. И читая его документацию на ss64, мы можем использовать опцию /B
, как это также сказано в комментарии Arjan и Nick Bolton. Таким образом, start /B bash -l !SHELL_ARGS!
также будет работать.
В моем случае это был файл ping.bat, который находился прямо в моем пользовательском каталоге (C:\Users\ в Vista или C:\Documents and Settings\ в XP), который задерживал выполнение пакетного задания неопределенно долго.
Этот пакетный файл выполнялся всякий раз, когда я запускал ping из командной строки, где текущим каталогом был мой пользовательский каталог. Пинг с окна выполнения или из другого пользовательского каталога работал хорошо.
Удалил файл из своего пользовательского каталога и проблема была решена!
Просто перенаправьте stdin пакетного файла на null, добавив < nul в конец команды.
Я столкнулся с этой проблемой с EXE, который, похоже, вызывал ^C для родительского пакета при выходе, вызывая запрос “Terminate Batch Job” даже при чистом выходе.
Решение, которое я выбрал, заключалось в запуске пакета с “Start”, аналогично другим ответам, но из окна PowerShell (или через метод интерпретатора PowerShell из CMD, если вам так удобнее).
Сейчас 2018 год, и в Windows 10 Microsoft начала заменять CMD PowerShell в качестве предпочтительного командного интерфейса, поэтому он доступен в графическом интерфейсе по умолчанию.
Start
является псевдонимом для Start-Process.
При выполнении он просто запускается и возвращается. Таким образом, когда вы останавливаете запущенный процесс, не возникает запроса “Terminate Batch Job”.
По умолчанию он не ждет, поэтому для команды и ее аргументов не требуются дополнительные аргументы.
Использование start mything.exe -mythings -arguments
в моем пакетном файле работало идеально.
В PowerShell скрипты должны быть переданы с их путем для запуска, поэтому я запускаю свой пакетный файл как .\host.bat
.
Основной причиной для подавления “Terminate batch job (Y/N)” является запуск программы в цикле (например, перезапуск в случае сбоя).
Этот https://stackoverflow.com/a/8185270/1170023 помог привести к этому решению:
@ECHO OFF
rem предполагается, что вы установили pslist от sysinternals в PATH Windows
:RUN
echo Запуск GoldenEye Dedicated Server
start "" srcds.exe -console -game gesource +maxplayers 16 +map ge_complex
:LOOP
pslist srcds >nul 2>&1
if ERRORLEVEL 1 (
goto RUN
) else (
rem echo Выделенный сервер все еще работает
timeout /t 5 >nul
goto LOOP
)
Решение, только что обнаруженное в 2025 году, которое работает с большинством обернутых .exe: просто добавьте || CALL CALL
после запуска .exe.
Это заставляет cmd забыть о предыдущем прерывании, поэтому вопрос “Terminate batch job” не появляется. Не-нулевой errorlevel сохраняется
Основная идея этого заключается в следующем наблюдении: выполнение CALL <anything>
в той же строке или ()
-выражении просто игнорирует запрос на завершение, вызванный командой, предшествующей этому вызову. Таким образом, добавление || CALL CALL
подавляет вопрос “Terminate batch job”, сохраняя не-нулевой errorlevel, так как CALL CALL
является тихой, но не действительной командой.
Вот полный рабочий пример, где wrapper.bat является оберткой-запускателем для некоторого внешнего .exe (powershell.exe – всего лишь пример, я использовал его с python.exe, не должно иметь значения, кроме указанной ниже оговорки):
@powershell.exe "$DelayinSeconds = Read-Host -Prompt 'Enter how manys seconds to sleep'; start-sleep -Seconds $DelayinSeconds" || CALL CALL
@IF ERRORLEVEL 1 (ECHO Завернутое exe закончило или прервано, выход из пакета & EXIT /B 1)
@ECHO Ok, продолжаем запуск пакета
Оговорка: если код возврата .exe будет 0 при прерывании приложения, CMD не выполнит часть после ||
, поэтому появится сообщение “Terminate batch job”. Это поведение фактически зависит от .exe. Если “всегда продолжать” приемлемо для конкретного использования (например, это конец скрипта в любом случае), вы можете использовать метод безусловного подавления &CALL CALL
.
Эту оговорку можно проиллюстрировать вышеуказанным примером с powershell.exe:
Сценарий | Результат |
---|---|
Введите 5, когда вас спросят число, Нажать | сообщение о продолжении выполнения пакета |
Введите x , когда вас спросят число, Нажать |
ошибка преобразования, не-нулевой errorlevel от .exe, сообщение завершение выполнения пакета |
Нажмите Ctrl+C, когда вас спросят число | не-нулевой errorlevel от .exe, сообщение завершение выполнения пакета |
Нажмите Ctrl+Break, когда вас спросят число | не-нулевой errorlevel от .exe, сообщение завершение выполнения пакета |
Введите 5 , когда вас спросят число, Нажать,нажмите Ctrl+C во время ожидания |
не-нулевой errorlevel от .exe, сообщение завершение выполнения пакета |
Введите 5 , когда вас спросят число, Нажать,нажмите Ctrl+Break во время ожидания |
Оговорка: .exe не завершает немедленно и дает нулевой errorlevel после ожидания появляется Terminate batch job (Y/N)? |
В конце вашего скрипта просто добавьте следующую команду:
echo
Это не повредит поведение вашего скрипта, и кажется, что это предотвращает появление запроса CMD, если вы хотите завершить работу пакета.
.
Ответ или решение
Подавление подтверждения "Terminate batch job (Y/N)" в командной строке Windows — это проблема, с которой сталкиваются многие пользователи, работающие с пакетными файлами. Это поведение возникает, когда вы пытаетесь завершить выполнение приложения, вызываемого из пакетного файла, с помощью сочетания клавиш Ctrl+C, и система спрашивает, хотите ли вы завершить весь пакетный процесс. Но есть несколько методов избежать этого нежелательного запроса.
Способы подавления
-
Перенаправление стандартного ввода
Один из простых и эффективных способов подавить это сообщение — перенаправить стандартный ввод пакетного файла на null. Это можно сделать, добавив оператор< nul
в команду запуска:script.cmd < nul
Таким образом пакетный файл будет завершен без запроса на подтверждение.
-
Изменение логики выполнения в самом скрипте
Используйте конструкцию в вашем скрипте, которая проверяет специальные флаги и перезапускает сам себя с модифицированным вводом:rem Bypass "Terminate Batch Job" prompt. if "%~1"=="-NO_TERMINATE_PROMPT" ( SHIFT ) ELSE ( CALL <NUL %0 -NO_TERMINATE_PROMPT %* GOTO :EOF )
Этот метод автоматически обрабатывает сценарии, вызываемые с параметром
-NO_TERMINATE_PROMPT
. -
Использование стороннего ПО: Clink
Установив программу Clink и изменив опциюterminate_autoanswer
, можно автоматически отвечать "Y" при выполнении Ctrl+C:clink set cmd.auto_answer answer_yes
Это настройка автоматически применится ко всему, что запускается в
cmd.exe
. -
Запуск отдельных процессов
Чтобы избежать проблемы вовсе, можно использовать командуstart
для запуска вашего приложения, отделяя его выполнение от командной строки:start my_command.exe my_params
Это создаст новый процесс, и завершение его не повлияет на текущую работу командной строки.
-
Переключение на альтернативный интерпретатор команд
Рассмотрите возможность использования альтернативных оболочек, таких как PowerShell или TCC/LE, которые предлагают широкие возможности настройки, включая отключение запроса на завершение пакетного задания.
Советы по оптимизации
- Использование инструментария AutoHotkey может автоматизировать нажатие Y при появлении запроса, делая это за пользователя.
- Поддержание чистоты вашей пользовательской директории от ненужных скриптовых исполняемых файлов может помочь избежать неожиданных вызовов и взаимодействий, которые вызывают "Terminate batch job".
Эти методы предлагают множество способов решить проблему, зависящую от специфических требований и контекста ваших задач. Выбор правильного подхода будет зависеть от ваших специфических условий использования, предпочтений и сред выполнения.