Подтвердить что ты не робот

Почему приложение GUI блокирует пакетный файл?

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

Несколько из многих ссылок, в частности, из SO/SE:

Кроме того, я сам помню, что это правда.

Но похоже, что это не так.

Я тестировал это в простом командном файле, например:

echo Pre
notepad
echo Post

Post не печатается, пока я не закрою блокнот. Почему, когда блокнот - это графическое приложение?

Я тестировал это на Windows 8, 7 и XP, чтобы исключить возможность изменения поведения в последних версиях Windows. Я попытался отключить расширения команд как один из возможных виновников.

4b9b3361

Ответ 1

Это связано с тем, как запускаемое и завершаемое приложение запускается. Некоторые программы запускают другой процесс, а затем завершаются, другие продолжают работать. Calc.exe и Notepad.exe просто запускаются до тех пор, пока вы их не закроете. Write.exe и любую программу, которая запускается в результате ассоциации файлов (например, растровый, волновой файл, апплет панели управления и т.д.), Фактически запускает другую программу, а затем процесс, который их запускает, завершает возврат управления обратно в пакетный файл поэтому он может выполнить следующую строку.

Вот несколько примеров:

@echo off

echo Starting Calc.exe
calc.exe
echo Calc was closed by the user

echo Starting Notepad.exe
Notepad.exe
echo Notepad was closed by the user

echo Starting WordPad.exe
write.exe
echo Write launched WordPad and then terminated allowing the batchfile to continue

echo Starting Services.msc
services.msc
echo Windows launched MMC, opened services.msc, then returned control to the batchfile

echo Launching WMP via Chord.wav
c:\windows\media\chord.wav
echo Windows launched WMP, opened Chord.wav, then returned control to the batchfile

Процесс CMD знает, что Calc и Notepad все еще работают, потому что они сами породили их. Процесс CMD не знает, что остальные все еще работают, потому что промежуточный процесс завершен.

Чтобы наблюдать это, откройте Process Explorer и просмотрите процессы, отображаемые в иерархическом дереве. Calc.exe и Notepad.exe остаются как дочерние процессы CMD-процесса, которые запускают пакетный файл. Write.exe и MMC.exe(services.msc) становятся процессами верхнего уровня, а не дочерними процессами CMD. WMPlayer.exe остается дочерним процессом для svchost.exe, каким образом Windows запустила его. Процесс CMD не знает, что они все еще работают, потому что он не запускал их, как это делал другой процесс Windows. Поэтому выполнение продолжается...

Еще один пример этого - как работает MSPaint.exe. Если вы запустите его, используя встроенную ассоциацию файлов Windows для BMP, тогда Windows запускает MSPaint.exe, и управление немедленно возвращается в пакетный файл. Однако, если вы передаете BMP в MSPaint.exe, тогда пакетный файл ждет вас, чтобы закрыть MSPaint перед продолжением. (Я на dev-машине без BMP, поэтому создайте простой файл C:\MyBitmap.bmp.)

@echo off
C:\MyBitmap.bmp
calc.exe
mspaint.exe C:\MyBitmap.bmp
notepad.exe

Calc.exe немедленно откроется, Notepad.exe не откроется, пока вы не закроете второй экземпляр MSPaint.exe.

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

Ответ 2

Потому что он ждет кода возврата. Вы можете использовать команду start для создания отдельного подпроцесса:

@echo pre
@start "notepad" notepad
@echo post

Ответ 3

Я использовал Windows с NT 3.1, и я тоже сказал бы: "cmd.exe не ждет завершения программ GUI", когда вы просто вводите имя программы (в отличие от использования команды START). Хотя память становится тусклой, я считаю, что она изначально работала именно так. Но сегодня мое утверждение истинно интерактивно, ложно для "пакетных" файлов. Напомнив об этом, я смутно думаю, что это было намеренно изменено как некоторый момент, поскольку наивный автор партии ожидает последовательного выполнения, но я не могу быть уверенным, и я не знаю, когда.

Ответ 4

Я думаю, что ответ кроется в этом вопросе Разница между Windows и консольным приложением.

Я цитирую два ответа.

Конрад Рудольф ответил:

Единственное отличие заключается в том, что консольное приложение всегда создает консоль, если она не запускается с одного (или консоль активно отключается при запуске). С другой стороны, приложение Windows не создает консоль. Он все равно может прикрепляться к существующей консоли или создавать новый с помощью AllocConsole.

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

oefe ответил:

Консоль и приложения Windows ведут себя по-разному, когда вызываются в интерактивном режиме из командной строки:

Когда вы запускаете консольное приложение, командная строка не возвращается, пока консольное приложение не выйдет. Когда вы запускаете приложение Windows, команда немедленно возвращается.

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

Разница в этом bahviour между cmd и пакетом заставила вас думать, что он работал раньше.