Как отключить подтверждение “Terminate batch job (Y/N)”?

Вопрос или проблема

В 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.

Оригинальное консольное окно исчезает, а новое можно чисто остановить с помощью CtrlC.

Рассмотрим следующий пример 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 ранее, вот некоторые сведения с сайта:

TCC/LE – это замена для командной строки CMD (стандартный командный интерпретатор Windows). TCC/LE является надмножеством CMD, с 111 внутренними командами (CMD имеет меньше чем 40), 240 внутренними переменными и функциями, и сотнями усовершенствований для существующих команд CMD.

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

Я использовал TCC/LE в течение многих лет и 4NT до него. У меня очень хорошие чувства к нему, и я могу его рекомендовать. Единственная причина, по которой я больше его не использую, это то, что я почти исключительно использую PowerShell теперь.

Смотрите этот вопрос на Stack Overflow.

Однако патчить cmd.exe – это не то, что я стал бы делать ради этого.

Решение с использованием AutoHotkey

  1. Скачайте и установите AutoHotkey

  2. Создайте скрипт (например, terminate.ahk)

  3. Вставьте следующий скрипт

#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}
}

  1. Выполните скрипт

Теперь, когда вы нажимаете 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, и система спрашивает, хотите ли вы завершить весь пакетный процесс. Но есть несколько методов избежать этого нежелательного запроса.

Способы подавления

  1. Перенаправление стандартного ввода
    Один из простых и эффективных способов подавить это сообщение — перенаправить стандартный ввод пакетного файла на null. Это можно сделать, добавив оператор < nul в команду запуска:

    script.cmd < nul

    Таким образом пакетный файл будет завершен без запроса на подтверждение.

  2. Изменение логики выполнения в самом скрипте
    Используйте конструкцию в вашем скрипте, которая проверяет специальные флаги и перезапускает сам себя с модифицированным вводом:

    rem Bypass "Terminate Batch Job" prompt.
    if "%~1"=="-NO_TERMINATE_PROMPT" (
      SHIFT
    ) ELSE (
      CALL <NUL %0 -NO_TERMINATE_PROMPT %*
      GOTO :EOF
    )

    Этот метод автоматически обрабатывает сценарии, вызываемые с параметром -NO_TERMINATE_PROMPT.

  3. Использование стороннего ПО: Clink
    Установив программу Clink и изменив опцию terminate_autoanswer, можно автоматически отвечать "Y" при выполнении Ctrl+C:

    clink set cmd.auto_answer answer_yes

    Это настройка автоматически применится ко всему, что запускается в cmd.exe.

  4. Запуск отдельных процессов
    Чтобы избежать проблемы вовсе, можно использовать команду start для запуска вашего приложения, отделяя его выполнение от командной строки:

    start my_command.exe my_params

    Это создаст новый процесс, и завершение его не повлияет на текущую работу командной строки.

  5. Переключение на альтернативный интерпретатор команд
    Рассмотрите возможность использования альтернативных оболочек, таких как PowerShell или TCC/LE, которые предлагают широкие возможности настройки, включая отключение запроса на завершение пакетного задания.

Советы по оптимизации

  • Использование инструментария AutoHotkey может автоматизировать нажатие Y при появлении запроса, делая это за пользователя.
  • Поддержание чистоты вашей пользовательской директории от ненужных скриптовых исполняемых файлов может помочь избежать неожиданных вызовов и взаимодействий, которые вызывают "Terminate batch job".

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

Оцените материал
Добавить комментарий

Капча загружается...