Why GUI application blocks a batch file? - 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.

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.

Because it waits for return code.You can use start command to create a separate subprocess:
#echo pre
#start "notepad" notepad
#echo post

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.

I think the answer lies in this question Difference between Windows and Console application.
I quote from two answers.
Konrad Rudolph answered:
The sole difference is that a console application always spawns a console if it isn't started from one (or the console is actively suppressed on startup). A windows application, on the other hand, does not spawn a console. It can still attach to an existant console or create a new one using AllocConsole.
This makes Windows applications better suited for GUI applications or background applications because you usually don't want to have a terminal window created for those.
oefe answered:
Console and Windows applications behave differently when called interactively from the command prompt:
When you start a console application, the command prompt doesn't return until the console application exits. When you start a windows application, the command returns immediately.
This is not true for batch files; they will always wait until the application exits.
The difference in this bahviour between cmd and batch made you think that it worked before.

Related

Why running .bat file thru Task Scheduler is not starting the .Jar file fully?

Here is what is going on. I have created a .Bat file containing start javaw -jar BTG_Producer.jar When I start this manually by double clicking it will show my java program in my system tray and shows the process "javaw.exe *32" in Windows Task Manager. When I run this thru Task Scheduler it starts the process "javaw.exe" with out the *32 and does not show the program in the system tray. Do you guys know what I am doing wrong?
When you launch a process via Task Scheduler, it may have a different environment than when you launch the process from your desktop. To test this, you can create a task that runs cmd with the /k parameter from the Task Scheduler. When you run it, cmd will open, then you can run set >%userprofile%\Desktop\environment1.txt. Then, open a cmd as you normally do, and run set >%userprofile%\Desktop\environment2.txt. Open the two files side by side, and compare.
In this case, I suspect your PATH variables are different, which is why 32-bit java is run in one case, and 64-bit in another.
To fix this, you could explicitly specify the 64-bit javaw.exe in your batch file.
C:\path\to\javaw.exe instead of just javaw.

How to run batch file via task scheduler to route print and keep the DOS window open/command line available to add text

in advance, thank you for any insight you may be able to offer. i know that there is a very similar post to my scenario and i have tried all variations of the answer but cannot get it to work for me as per the initial or edited instructions. in order to circumvent the uac nags, i am running windows 7 (64 bit) and trying to run a batch file to simply 'route print cmd /k' via task scheduler and desktop shortcut but i want the DOS window to remain open and allow me to continue typing into it. when i execute the actual file, it runs as desired, however when it runs via task scheduler, the dos window closes immediately. to no avail, i have tried multiple things such as changing the 'program/script' field from C:\location\batchfilename.bat to just cmd and inputting the various arguments including cmd /k or /k or /k C:\location\batchfilename.bat to the task's 'add arguments' field and/or the batch script itself. although i do not want pause as it would close the window after pressing any key, i have also tried it in the script itself and the arguments field but it too does not keep the dos window open when running as scheduled task. nothing seems to work - your help is greatly appreciated!

Pipe command to specific cmd.exe

So I've written a .bat file (later on refered to as the 2nd one) to backup files every night and then weekly offsite to ensure the files aren't lost. However I realized that a process may be running and currently editing the files so it'd be best to shut down the process and then start it again once the backup is done.
Now, the main problem is this: The process is another batch file running under cmd.exe. There is also a java.exe command window that is created in conjunction with the cmd.exe, and entering the stop into either the cmd.exe or java.exe windows produces the same and the process will stop their process safely. With that in mind I've tried the following commands (minus the *s),
echo stop | cmd.exe
echo stop | java.exe
but what I find is that the cmd.exe pipe is just sending the command to the command window opened by the 2nd batch file. Meanwhile the java.exe command returns an error in the 2nd batch file on how that the proper parameters weren't used.
That being said my main question is this:
Is it possible to pipe commands to specific cmd windows, if so how?

Sequentially run batch code

Probably a really obvious question, I'm trying to run some sequential batch code to define my own eclipse external run configurations.
One of the calls in the .bat is to run a jetty server, and after this I want to launch a program. At the moment the execution of the .bat means that the call to run jetty hangs on that call, and the call to open the program is only executed once the jetty server has been killed.
Is there any way I can run the call to start jetty, and then immediately run another call to open any program that wont have to wait for the server to be killed.
You can use start to run a program in the background explicitly:
start "" "C:\Program Files\etc.\blah\x.exe"
Execution of the batch file immediately continues after that line. In case of jetty you're probably starting Java anyway. cmd doesn't wait for GUI processes so you can also use
javaw -jar ...\jetty.jar
instead of calling java.
Since the question has changed a bit after the comment:
If there is a reliable way of knowing when jetty has started, e.g. a file that will exist somewhere
:l
timeout /t 1 >nul
if not exists %temp%\somefile goto l
you could use that. Otherwise you can just wait for a while
rem wait two minutes
timeout /t 120 > nul
and hope that everything has started by then.

Start Play Application and Close Window

I have a play application on a Windows 7 machine which I want to start via double click on a batch file.
This batch file starts a service. Calls the play application to run in production mode, waits for 5 seconds and open a browser with a specified url.
Therefore I used the following script:
call net start service1
CALL "D:\play-1.2.5\play.bat" start --%%%%prod -Dprecompiled=true
TIMEOUT /T 4
call "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" localhost:9000
exit
Now when I start the batch file the window opens and all commands are executed. Sadly Play is still writing his output to cmd and the window is not disappearing. If I close the window manually play is stop executing.
If I run play with "play start" from cmd, play is starting in the background and everything is fine. Play still runs even if I close the window.
I want to have exactly this behaviour when I start the application with my batch file.
Thanks
If you were using a linux-like environment, I' d recommend you to use 'nohup' command and a '&' sign in the end. However, as far as I know there is no direct equivalent of beautiful 'nohup' command on Windows, unfortunately. So, what I can think of is, you can create a tiny win api application that utilizes CreateProcess command and give it the required parameter to hide command line window as soon as the process is created. There are also other process creation functions such as WinExec that you can use to hide command line.
I don't know what Play is so I can only take a guess :) but try using the batch without the call's as I don't think they are necessary, and you never know, might fix the issue.
1) You see Play's output because ot redirect only system.out but write system.err to the same console.
2) I also have this problem and looking for a solution. As a workaround you could try to use some Java Wrapper and install your Play! application as a Windows Service.
3) Play! app could be started via Ant task. I haven't tried this yet.

Resources