4

I have an Swing application in which the user can create and save documents. The application is deployed as a simple Jar-file.

The primary target platform is Windows Vista.

If the user has on opened and non-saved document in the application and the user is logging out from the Windows Vista machine I would like to halt the logging off process and ask the user if he wants to save to document before the Java application is terminated.

Is it possible to halt the logging off process on Windows Vista from an Java application?

I've tried the shutdown hook with no success.

AakashM
  • 62,551
  • 17
  • 151
  • 186
Mattias
  • 41
  • 2

2 Answers2

3

Is it possible to halt the logging off process on Windows Vista from an Java application?

No, nor should it be possible. That's like the tail wagging the dog.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • Either I misunderstood something, either the behaviour is asking is about what every editing app (Word, Notepad++, Eclipse, ...) is doing, ie, asking if the user wants to save his changes, discard them or cancel the current shutdown process. I don't see any problem in doing that. Eventually, Windows will ask if you want to kill the process or cancel the shutdown – Guillaume Polet Apr 10 '12 at 07:40
  • I focused on the words *"logging out from the Windows Vista machine"* AFAIU what you are suggesting will work for when the user exits our app., but not for exiting the OS. – Andrew Thompson Apr 10 '12 at 07:44
  • Yes, but actually what I am suggesting does work and you can end up halting the logging off process. Windows will first try to close all the application frames. If the process does not end within a time interval (around 30 seconds), Windows will ask wheter you would like to force shutdown of the app or cancel the logging off process, ie, this will cancel exiting the OS. – Guillaume Polet Apr 10 '12 at 07:46
  • (reconsiders) Actually, you might be right about that. But it would take a shutdown-hook to detect the condition, wouldn't it? – Andrew Thompson Apr 10 '12 at 07:47
  • From what I know/understand, in a Swing app, it is like Windows tried to press the red cross of your active JFrame (or the last activated). So if you register a window adapter, you can do it from the windowClosing method. It can probably also work from a shutdown-hook, I think that the important thing is to keep the EDT "alive" using a blocking call like with a JOptionPane or a JDialog – Guillaume Polet Apr 10 '12 at 07:50
  • I was definitely at least partly wrong in my presumptions. There is now code & a screenshot edited into my question that seems to support your view (at least partially). Unfortunately the further code/screenshot does not fit well with my existing answer. Care to wedge the code/screenshot into your answer (where it makes more sense)? – Andrew Thompson Apr 10 '12 at 08:18
  • OK, I integrated your proposal into my answer. Don't hesitate to edit my answer if you feel it is incorrect or not properly presented. – Guillaume Polet Apr 10 '12 at 08:37
  • Looks good, now the thread makes more sense to an external viewer. :) I'd +1 now, if I'd not already done that earlier. – Andrew Thompson Apr 10 '12 at 08:45
  • Yes. I'm looking for the same behavior as any other native applications like Word and Notepad. – Mattias Apr 10 '12 at 10:59
  • 1
    @AndrewThompson looks like I was wrong on this subject. I thought that it would be caught by the windowClosing event, but it looks like not (at least it did not work on Win7-64bits Java 1.6.0_24-64bits, 1.6.0_26-64bits, 1.6.0_31-64-bits nor 1.7.0_u2-64bits, same for Win7-64bits Java 1.6.0_24-32bits nor does it work on WinXP32-bits Java 1.7.0_u3-32-bits). Either the program is closed without asking either the frame hangs. None are good. I think though that we could try to catch a specific signal and act on it, but maybe I should throw a question on the matter. – Guillaume Polet Apr 10 '12 at 21:49
3

EDIT2


For those who followed the discussion I leave the first answers I had but it seems like they don't work. First find my real solution.

Ok, so I think this actually works but it is not totally acceptable as it used restricted part of the API (but it exists since Java 1.3 and is still present in Java 1.7). It uses sun.misc.Signal. Most of the code has been originally posted by Andrew Thompson.

import java.awt.AWTEvent;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import sun.misc.Signal;
import sun.misc.SignalHandler;

class TestShutDown {
    static final String WINDOW_MODIFIED = "windowModified";

    TestShutDown() {
        final JFrame f = new JFrame("Log Off!");
        f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        f.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent we) {
                System.err.println("Window closing");
                handleQuit(f);
            }

        });
        Signal.handle(new Signal("TERM"), new SignalHandler() {

            @Override
            public void handle(Signal arg0) {
                handleQuit(f);
            }
        });
        // bad practice, but not the point..
        f.setSize(400, 200);
        f.setLocationByPlatform(true);
        f.setVisible(true);
    }

    protected static void handleQuit(final JFrame f) {
        int result = JOptionPane.showConfirmDialog(f, "Close Me");
        if (result == JOptionPane.OK_OPTION) {
            System.exit(0);
        }
    }

    public static void main(String[] args) {
        // start the GUI on the EDT
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestShutDown();
            }
        });
    }
}

SOLUTION EARLIER SUGGESTED (NOT WORKING ON LOGOFF)

I am assuming that you are using a GUI application with a JFrame.

In your JFrame, set the following:

setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);

Then, register a WindowAdapteron your JFrame. Override the windowClosing() method and from there open a blocking dialog to ask the user what he wants to do (Yes/NO/CANCEL). In case he chooses, YES, you save and then dispose the frame, in case he chooses NO, you just dispose the frame. If he chooses cancel, you don't do anything.


EDIT:

Here is some code and more details on what I was explaining and that have been brought by Andrew Thompson. All credits should go to him for the following:

Using this code:

import java.awt.event.*;
import javax.swing.*;

class TestShutDown {

    TestShutDown() {
        final JFrame f = new JFrame("Log Off!");
        f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        f.addWindowListener( new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent we) {
                int result = JOptionPane.showConfirmDialog(f, "Close Me");
                if (result==JOptionPane.OK_OPTION) {
                    System.exit(0);
                }
            }
        });
        // bad practice, but not the point..
        f.setSize(400,200);
        f.setLocationByPlatform(true);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        // start the GUI on the EDT
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestShutDown();
            }
        });
    }
}

Then telling Windows to shut down, I see..

Windows refusing to shut-down

Even more interestingly, after I hit Cancel ( heck, 'Searching for UFOs' was the next queued track in the player, and I was not about to reschedule it :), I could not click on the frame. It seemed as though it was blocked with an invisible modal dialog. I had to kill the VM to be rid of it.

Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117
  • Thx for quick answers. I've tried the code above with no success. The Java process is killed without that the dialog appears. – Mattias Apr 10 '12 at 10:58
  • More details please. Did you see a screen similar to the one shown above? Were you listening to pumping acid dance tracks at the time? ( OK just joking on that one ;) What option did you select from that screen? .. – Andrew Thompson Apr 10 '12 at 11:40
  • I run the Java code TestShutdown and gets a nice grey JFrame. If I hit the cross to close the frame I get the JOPtionPane When I selecting Log Off in the Windows Start menu. I got logged off without any question and I don't get the dialog "XX programs still need to close:". The Java application is just terminated. If I start Notepad and have an open unsaved document and log off I got the "XX programs still need to close:" with the text that it is Notepad that prevents Windows to close. Java version: 1.6.0_16 Windows Vista Enterprise SP2 32-bit – Mattias Apr 10 '12 at 12:40
  • @Mattias I will look into this because I have another program which uses the exact same technique and it works like a charm – Guillaume Polet Apr 10 '12 at 17:27
  • @Mattias looks like I was wrong on this subject. I thought that it would be caught by the windowClosing event, but it looks like not (at least it did not work on Win7-64bits Java 1.6.0_24-64bits, 1.6.0_26-64bits, 1.6.0_31-64-bits nor 1.7.0_u2-64bits, same for Win7-64bits Java 1.6.0_24-32bits nor does it work on WinXP32-bits Java 1.7.0_u3-32-bits). Either the program is closed without asking either the frame hangs. None are good. I think though that we could try to catch a specific signal and act on it, but maybe I should throw a question on the matter. – Guillaume Polet Apr 10 '12 at 21:48
  • Thanks for the comprehensive report. *"maybe I should throw a question on the matter."* I'm not confident anyone else (including e.g. Oracle in a bug report) will be deeply interested, given the apparent answer is "add a shutdown hook". You *are* still talking about code **without** a shutdown hook, right? – Andrew Thompson Apr 10 '12 at 22:06
  • @AndrewThompson I found a solution without using the shutdown hook (but maybe it does the same thing, I haven't tried) using Signals. Btw, a bug looking like the freeze you talked seems to be present in Oracle DB: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073451 ... unfixed for now. – Guillaume Polet Apr 10 '12 at 22:22
  • `sun.misc` (shudder) You are a determined (& brave) person. ;) The last comment on that bug report suggests it actually works on at least one version of 1.7, but I am unable to relate that type of version number directly to your version. Still, I don't suppose it is that important given you found two JRE 7 versions in which it breaks. – Andrew Thompson Apr 10 '12 at 23:38