Как предотвратить закрытие командной строки после выполнения?

55

Моя проблема в том, что в Windows есть окна командной строки, которые закрываются сразу после выполнения. Чтобы решить эту проблему, я хочу, чтобы по умолчанию было открыто окно. Обычно такого поведения можно избежать тремя способами, которые приходят мне в голову:

  1. Поставить pauseстроку после пакетных программ, чтобы предложить пользователю нажать клавишу перед выходом
  2. Запуск этих командных файлов или других инструментов для работы с командной строкой (даже запуск службы, перезапуск и т. Д. С помощью net start xyчего-либо подобного) в cmd.exe(Пуск - Выполнить - cmd.exe)
  3. Запуск этих программ с помощью cmd /kэтого: cmd /k myprogram.bat

Но есть и другие случаи, когда пользователь:

  1. Запускает программу в первый раз и не знает, что данная программа будет запускаться в командной строке (Windows Command Processor), например, при запуске ярлыка из меню «Пуск» (или из другого места), ИЛИ
  2. Несколько неудобно постоянно запускать cmd.exe, и у него нет времени / возможности везде переписывать код этих команд, чтобы ставить после них паузу или избегать явного выхода.

Я прочитал статью об изменении поведения по умолчанию cmd.exeпри его явном открытии с созданием записи автозапуска и манипулированием ее содержимым в следующих местах:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor\AutoRun
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Command Processor\AutoRun

(Элементы автозапуска _String values_...)

Я положил cmd /d /kв качестве значения, чтобы он попробовал, но это совсем не изменило поведение упомянутых выше вещей ... Он просто изменил поведение окна командной строки при его явном открытии (Start-Run- cmd.exe).

Итак, как это работает? Можете ли вы дать мне какие-либо идеи для решения этой проблемы?

Sk8erPeter
источник
10
Ваш вопрос со всеми объяснениями заставил мою голову взорваться. Можете ли вы сказать что-то вроде: я хочу запустить командный файл с помощью этой команды «примера», и я хочу, чтобы окно команды оставалось открытым после завершения. Это то, что вы спрашиваете? Пожалуйста, вставьте пример кода.
Котро
1
+1 Согласен. Немного подробный, пожалуйста, пересмотрите свой вопрос и, если возможно, используйте пример и составьте более сжатый вопрос.
slotishtype
2
Это нормальное поведение, и, хотя ваш вопрос, безусловно, действителен, вы должны задаться вопросом, почему вам нужно держать командную строку открытой после (большинство утилит создаются с учетом этого предостережения).
Прорыв
1
На мой взгляд, это не настоящий вопрос. Поскольку вы просто указываете пользователю использовать вместо этого пакетный файл. Если это не цель вопроса, пожалуйста, проясните свой вопрос, удалив всю запутанную информацию и объясните, какова ваша реальная цель. Трудно придумать правильный ответ, если неясно ...
Тамара Вийсман
1
@Randolf Richardson, это потому, что конечные пользователи никогда не должны видеть эти инструменты (в конце концов, именно поэтому мы сейчас используем GUI). Если вам нужна такая информация, большинство ИТ-групп будут отправлять командные файлы, чтобы собрать необходимую системную информацию и отобразить ее. Я не вижу никакого возможного способа, чтобы, если будет найдено решение этого вопроса, оно вызовет меньше проблем, чем решит - так много вещей отправляются stdoutна постоянной основе, которые никогда не были видны по уважительной причине.
Прорыв

Ответы:

27

У меня есть решение , которое может применяться только .cmdи .batфайлы:

Откройте regeditи перейдите к каждому из:

[HKEY_CLASSES_ROOT\batfile\shell\open\command]
[HKEY_CLASSES_ROOT\cmdfile\shell\open\command] 

Теперь измените «Значение ключа по умолчанию» на cmd.exe /k "%1" %*. Теперь каждое окно пакетного скрипта останется открытым после его выполнения.

Обратите внимание, что это похоже на использование cmd.exe /c cmd.exe /k program.bat, что означает, что другой экземпляр CMD будет запущен в родительский. Я не мог найти, как переписать первый /cаргумент.

Вы также можете сделать это с помощью [exefile], но теперь он покажет пустое поле консоли, если исполняемый файл имеет графический интерфейс.

not2qubit
источник
4
+1 за единственное решение, которое действительно отвечает на поставленный вопрос. К сожалению, я думаю, что это может быть утечка памяти, ожидающая, чтобы случиться. Что происходит, когда служба запускает новый пакетный файл без указания CMD.EXE в строке CMD? Не будет ли этот код использоваться в этом случае? Разве это не создаст новое окно на неинтерактивном рабочем столе и оставит его открытым до перезагрузки?
krowe2
@APerson Ваше изменение нарушило команду, не включая *. Пожалуйста, будьте осторожнее при редактировании!
not2qubit
@ not2qubit Извините, не заметил, что я удалил три звездочки вместо двух. Сделаю.
APerson
17

Цитата Microsoft :

Консоль закрывается, когда последний присоединенный к ней процесс завершается или вызывает FreeConsole.

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


(Для 16-разрядных программ MS-DOS Windows предлагает параметр «Закрыть при выходе» в диалоговом окне свойств, но это не исключение из описанного выше поведения: это процесс NTVDM, который держит окно открытым. Также эта опция снова за программу.)

grawity
источник
13
+1 за понимание того, как и почему закрываются окна консоли (в отличие от большинства, которые просто говорят: «Боже мой, почему он не остается открытым !!!!!!!!!!! 1111one»). Он ведет себя так, как задумано, и он должен оставаться таким, ИМХО. Это основная причина, по которой у нас есть стандартные потоки и командные файлы.
Прорыв
27
@ Прорыв Вопрос в том How can I do X, нет In your opinion, should I do X. Этот ответ бесполезен, он подразумевает, что X невозможно, когда частичные решения уже были представлены в другом месте. (-1)
Superbest
8

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

1. Перейдите в папку, в которой находится ваш исполняемый файл.
2. Щелкните правой кнопкой мыши Shift и выберите «Окно командной
строки ». 3. Введите имя исполняемого файла и нажмите Enter.
4. Процесс должен запуститься, но окно должно остаться открытым.

Ли Харрисон
источник
1
Я не знал о Shift + правый клик. Также, однако, вы можете перетащить исполняемый файл в окно cmd, которое автоматически указывает путь для вас.
Superbest
1
Это обычно работает для меня, но это, очевидно, не совсем так, потому что я здесь ищу решение именно потому, что оно не работает в моей текущей ситуации.
RenniePet
это самое простое решение и должно быть помечено как правильный ответ
Вики Кападиа
4

cmd.exe /kдаст вам проблемы с какой-то партией. Если партия exit 1(без /B), ваша консоль будет закрыта. Хитрость заключается в использовании:

cmd.exe /k cmd /c ...

Чтобы использовать эту функцию по умолчанию для всех пакетных файлов, набор HKEY_CLASSES_ROOT\cmdfile\shell\open\command\(default)и HKEY_CLASSES_ROOT\batfile\shell\open\command\(default)к "%windir%\system32\cmd.exe" /k "%windir%\system32\cmd" /c "%1" %*.

Wernight
источник
1
Я думал, что это "%*"передает полный список параметров, поэтому не будет ли это передать первый параметр дважды, один раз "%1"и снова, как первый параметр "%*"?
Кевин Феган
1
@KevinFegan Я не проверил причину, но% 1 должен сохранять кавычки, что означает, что в некоторых случаях он может быть заключен в двойные кавычки. Существует также разница между %1 %2 %3 ..и %*которую я не помню сейчас , кроме %1 %2 %3работ , в некоторых случаях , когда %*не удается.
Wernight
3

Я только что наткнулся на глупое решение после прочтения grawityответа.

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

Мое решение (только что протестированное на Win7) так же добавляется cmdкак последняя строка в командном файле. Это запускает вложенную командную строку, которая наследует среду своего родителя. Эта дочерняя оболочка удерживает пакетный процесс открытым до тех пор, пока вы не ВЫХОДИТЕ, после чего пакет не имеет дочерних процессов и также завершается.

kitsu.eb
источник
2

Вместо использования PAUSE (я предпочитаю, чтобы CHOICE или TIMEOUT использовали PAUSE, когда это необходимо), вы можете использовать решение здесь: 886848 / how-to-make-windows-batch-file-pause-when-double-click .

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

Используя CHOICE, вы можете запрограммировать возможность выбора пользователем различных действий, а использование TIMEOUT может позволить окну закрыться через некоторое время (без присмотра). Если вы запускаете командный файл из окна командной строки, эти паузы могут раздражать.

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

Вы можете прочитать больше по предоставленной ссылке, но ее основа в том, что она использует переменную окружения:

%cmdcmdline%

определить, был ли командный файл запущен из командного окна или нет.

Итак, вы используете это так:

В тот момент, когда пакетный файл будет завершен, вы добавите некоторый код, подобный этому:

echo %cmdcmdline:"=-% | find /i "cmd /c --%~dpf0%-"
if %errorlevel% NEQ 0 goto :EOF
pause
goto :EOF

rem if %errorlevel% EQU 0 batch-file: %~dpf0 was executed from Windows Explorer, ...
rem if %errorlevel% NEQ 0 batch-file: %~dpf0 was executed from within a Command Prompt
Кевин Феган
источник
1

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

поэтому, если вы обычно запускаете файл с именем go.bat, то вы создадите второй пакетный файл с именем что-то вроде go2.bat

содержимое go2.bat будет просто

start go.bat

первое окно закрывается сразу, но то, что запускает ваш go.bat, остается открытым

agradl
источник
Это работает, я просто поместил имя исполняемого файла командной строки в один файл bat (1.bat), который вызывается командой start из второго файла bat "start 1.bat". Командное окно остается открытым.
ejectamenta
1

Это работает для версии 5.00 редактора реестра Windows.

[HKEY_CLASSES_ROOT\batfile\shell\open\command]
@="cmd.exe /k \"%1\" %*"

[HKEY_CLASSES_ROOT\cmdfile\shell\open\command]
@="cmd.exe /k \"%1\" %*"

Сохраните вышеупомянутые cmds в файле с именем что-то вроде cmdbatfile-open.regи выполните его!

VumC
источник
2
Добро пожаловать в Stack Exchange! Я исправил форматирование в вашем ответе для вас. Смотрите здесь для справки форматирования. Кроме того, когда вы публикуете код, не забудьте объяснить, что именно он делает. Вы также можете прочитать инструкции по ответам .
Сияющий
1

Предположим, у вас есть два пакетных файла, которые вы хотите запустить в своем собственном экземпляре и держать открытыми, если их исполняемый файл завершается. Давайте назовем эти две партииA.bat и B.bat.

Теперь для простоты у вас может быть командный файл для их запуска, давайте назовем это launch_both.batс содержимым:

start cmd /k "A.bat & cmd /c"
start cmd /k "B.bat & cmd /c"

Это может работать не так, как ожидалось, если вы вызываете exitодин из двух пакетных файлов. Это нужно будет проверить.

Francois
источник
0

Для пользователей, использующих Windows 10, обратите внимание, что ни один из ответов выше в настоящее время не работает для Windows 10.

Для Windows 10, если у вас есть доступ к сценарию, вам нужно добавить следующий код в конце:

read

Этот код будет ждать ввода перед закрытием.

jaycode
источник
Помните, что вопрос задавался до Windows 10 (5 лет назад), пожалуйста, отредактируйте свой ответ с более подробной информацией
yass
0

В ответ на пониженную версию PSIXO - «Этот ответ уже был рассмотрен в вопросе. - Ro Yo Mi Jan 20 '16 в 5:06» - НЕТ, это было НЕ. Предыдущие ответы были: «пауза», которая НЕ работала. PSIXO ответил: «& пауза», которая работает. Пожалуйста, проанализируйте более внимательно, прежде чем понизить. Я запустил это из приглашения IDLE, и это сработало:

    >>> os.system('dir ^ & pause')
    0
    >>> 

С другой стороны:

    >>> os.system('dir ^ pause')
    1
    >>>

НЕ работало (приглашение cmd перевернулось и фактически вернуло ошибку (1)). Спасибо PSIXO за ответ, который мне был нужен. Генри.

Генри
источник