I have a bat script which runs a java application. If I press ctrl+c on it, it the application terminates gracefully, invoking all the shutdown hooks. However, if I just close the cmd window of the bat script, the shutdown hooks are never invoked.
Is there a way to solve this? Perhaps there's a way to tell the bat script how to terminate the invoked applications when its window is closed?
Though the batch file may be terminated, the console (window) the batch file has been running in may be left open, depending on the operating system, the command processor, and how batch file execution was started (from a command prompt or through a shortcut).
taskkill
is a good command for ending a program which is distributed with Windows (I'm assuming you want to stop a DIFFERENT program, not the batch file itself).It is possible to end programs by process id, executable name, window title, status (i.e. not responding), DLL name, or service name.
Here are some examples based on how you might use this in your batch file:
Force "program.exe" to stop (often the /f "force" flag is needed to force the program to stop, just check whether it is needed for your application by trial and error):
Stop any non-responsive programs:
Stop a program based on its window title (* wildcard is allowed here to match anything):
You can even use it to stop a program on another computer on your network (although writing the password of an account in a batch file is just not a good idea).
Another alternative also distributed with Windows is
tskill
. Although it doesn't have nearly as many options, the commands are a bit simpler.EDIT:
I am not sure there is. I would think that closing the cmd window is akin to
force-closing
the app i.e. immediate termination with no further notice. This has the behavior of many applications that, when they are asked toforce-close
, they actually take a long time to finally terminate. This is because in the OS's efforts to release all resources, some resources (especially certain I/O and/or file resources) don't let go immediately.IMO, there's nothing Java could even do about it if it wanted to. A force-close happens at the OS level, at which point it releases the memory, file and I/O handles in use, etc. Java does not (nor does any other program) have control over a force-close. At this point, the OS is taking charge.
Someone please correct me if I'm wrong.
From addShutdownHook documentation:
So i think nothing to do here, unfortunately.
CTRL-CLOSE signal in Windows Console. Seems non-tweakable.
Quoting above link:
ExitProcess
to terminate the process.FALSE
. If none of the registered handler functions returnsTRUE
, the default handler terminates the process.TRUE
. In this case, no other handler functions are called, and a pop-up dialog box asks the user whether to terminate the process. If the user chooses not to terminate the process, the system does not close the console until the process finally terminates.UPD. If native tweaks are acceptable for you, WinAPI
SetConsoleCtrlHandler
function opens way for suppressing of default behavior.UPD2. Revelations on Java signal handling and termination relatively old article, but section Writing Java signal handlers really may contain what you need.
UPD3. I've tried Java signal handlers from article above. It works with
SIGINT
nicely, but it not what we need, and i decided to carry it withSetConsoleCtrlHandler
. The result is a bit complicated and may be not worth to implement in your project. Anyway, it could help someone else.So, the idea was:
CTRL+CLOSE
signal.Java code:
Native
replaceConsoleHandler
:And handler itself:
And it works. In JNI code all error checks are omitted for clearance. Shutdown handler creates empty file
"d:\shutdown.mark"
to indicate correct shutdown.Complete sources with compiled test binaries here.
Further to the above answer of using SetConsoleCtrlHandler, you can also do this using JNA rather than writing your own native code.
You could create your own interface on kernel32 if you wanted, or use the one provided in this excellent framework: https://gitlab.com/axet/desktop
Some example code:
Note that I assigned the anonymous class to a field. I originally defined it in the call to SetConsoleCtrlHandler, but I think it was getting collected by the JVM.
Edit 4/9/17: Updated link from github to gitlab.