Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why GUI application blocks a batch file?

Tags:

batch-file

There are many references on Internet claiming that one of differences between a GUI and a console application is that running the GUI application from a batch file does not block its execution, while running the console application does block it.

Few of many references, these are particularly from SO/SE:

  • How can I get an MFC application to block from the command line?
  • How to wait for a process to terminate to execute another process in batch file
  • How do you wait for an exe to complete in batch file?
  • Run a program in a batch script and wait for it to finish before continuing

Moreover, I myself remember this is/was true.

Yet it does not seem to work this way.

I've tested this on a simple batch file like:

echo Pre
notepad
echo Post

The Post is not printed until I close notepad. Why, when a notepad is clearly a GUI application?

I've tested this on Windows 8, 7, and XP just to rule out a possibility that the behavior has changed in recent versions of Windows. I've tried to disable command extensions as one of possible culprits too.

like image 727
Martin Prikryl Avatar asked Oct 15 '13 12:10

Martin Prikryl


3 Answers

It has to do with how the application that you launch runs and terminates. Some programs launch another process and then terminate, others continue to run. Calc.exe and Notepad.exe simply run until you close them. Write.exe and any program that launches as a result of a file association (e.g., bitmap, wave file, control panel applet, etc.), actually launch another program and then the process that launched them terminates returning control back to the batch file so it can execute the next line.

Here are some examples:

@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

The CMD process knows Calc and Notepad are still running because it spawned them itself. The CMD process does not know that the others are still running because the intermediate process terminated.

To observe this, open Process Explorer and view the processes displayed in the hierarchical tree. Calc.exe and Notepad.exe both remain as child processes of the CMD process that ran the batchfile. Write.exe and MMC.exe (services.msc) both become top-level processes, no longer children to the CMD process. WMPlayer.exe remains a child process to svchost.exe, which is how Windows launched it. The CMD process doesn't know they are still running because it didn't launch them, some other Windows process did. So execution continues...

One more example of this is how MSPaint.exe functions. If you run it by using the Windows built-in file association for BMPs, then Windows launches MSPaint.exe and control is immediately returned to the batchfile. However, if you pass the BMP to MSPaint.exe, then the batchfile waits for you to close MSPaint before continuing. (I'm on a dev machine with no BMPs, so create a simple one called C:\MyBitmap.bmp.)

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

Calc.exe will open immediately, Notepad.exe will not open until you close the second instance of MSPaint.exe.

I know you didn't ask about launching Windows processes via their file association, but it just demonstrates how the owning process can change. If the CMD process owns the launched process, it should wait until it terminates to continue execution. If the spawned process hands control off to another process, then the CMD process doesn't know about the grandchild process and it continues on with its execution.

like image 102
James L. Avatar answered Sep 22 '22 18:09

James L.


Because it waits for return code.You can use start command to create a separate subprocess:

@echo pre
@start "notepad" notepad
@echo post
like image 30
npocmaka Avatar answered Sep 23 '22 18:09

npocmaka


I've used Windows since NT 3.1, and I too would have said "cmd.exe does not wait for GUI programs to terminate" when you simply type the name of the program (as opposed to using the START command). Though memory grows dim, I believe it originally worked this way. But today, my statement is true interactively, false for "batch" files. Having been thus reminded, I vaguely think it was intentionally changed as some point, since the naïve batch-writer expects sequential execution, but I can't be sure and I don't know when.

like image 25
dave Avatar answered Sep 21 '22 18:09

dave