Es gibt three different scenarios, wenn Sie Abschalt- und Abmeldeereignisse verarbeiten können. Ich werde mich auf die Windows-Anwendung konzentrieren, weil es auch für Konsolenanwendungen funktioniert und wenn Ihre Anwendung aus irgendeinem Grund die Funktionen von User32 importiert, funktioniert das Konsolenhandle nicht.
Grundsätzlich erhalten Sie 2 Funktionen benötigen:
ATOM RegisterClassEx(WNDCLASSEX *lpwcx);
RegisterClassEx eine neue Art von Fenster mit einem Haken erstellen (das unsere shutdown/Abmelde Handler) zugeordnet.
HWND WINAPI CreateWindowEx(
int dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName,
int dwStyle, int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam
);
CreateWindowEx instanziiert ein neues Fenster, das Fenster ein Ereignis Haken (von der registrierten Klasse) zugeordnet hat, auf diese Weise Windows den zugehörigen Haken mit all possible events benachrichtigen.
hier ein voll funktionstüchtiges Beispiel, starten Sie es einfach und Abmelde oder Herunterfahren des Computers, nachdem sie wieder beginnen, werfen Sie einen Blick auf %userprofile%\shutdown-hook.log
Datei muss diese Ereignisse behandelt haben durch so etwas wie
...
action=proc-callback, event=22
...
code Anmeldung
public class Main {
/**
* <pre>
* Steps:
*
* 1. Create a WinProc (this function will handle all events)
* 2. Create a window class using the created WinProc
* 3. Create a window using the created window class
* 4. Use the WinProc to handle shutdown events
* </pre>
*/
public static void main(String[] args) {
// registering a window - https://msdn.microsoft.com/pt-br/library/windows/desktop/ms633587
// https://msdn.microsoft.com/pt-br/library/windows/desktop/ms633577
// typedef struct tagWNDCLASSEX {
// UINT cbSize;
// UINT style;
// WNDPROC lpfnWndProc;
// int cbClsExtra;
// int cbWndExtra;
// HINSTANCE hInstance;
// HICON hIcon;
// HCURSOR hCursor;
// HBRUSH hbrBackground;
// LPCTSTR lpszMenuName;
// LPCTSTR lpszClassName;
// HICON hIconSm;
// } WNDCLASSEX, *PWNDCLASSEX;
//
// ATOM WINAPI RegisterClassEx(
// _In_ const WNDCLASSEX *lpwcx
// );
final WinUser.WNDCLASSEX clazz = new WinUser.WNDCLASSEX();
clazz.lpszClassName = "MyCustomWindow";
clazz.cbSize = Native.getNativeSize(WinUser.WNDCLASSEX.class, null);
clazz.lpfnWndProc = new MyWinProc();
WinDef.ATOM classInst = User32.INSTANCE.RegisterClassEx(clazz);
System.out.printf("action=registerclass, clazz=%s, error=%d\n", classInst, Native.getLastError());
WinDef.HWND w = User32.INSTANCE.CreateWindowEx(
512, clazz.lpszClassName, "My Window",
WinUser.WS_OVERLAPPEDWINDOW, -2147483648, -2147483648, 250, 100,
null, null, null, null
);
System.out.printf("action=createWindow, w=%s, error=%d\n", w, Native.getLastError());
WinUser.MSG msg = new WinUser.MSG();
while (User32.INSTANCE.GetMessage(msg, null, 0, 0)) {
User32.INSTANCE.DispatchMessage(msg);
}
}
public interface User32 extends Library {
User32 INSTANCE = Native.loadLibrary("User32", User32.class, W32APIOptions.UNICODE_OPTIONS);
// ATOM WINAPI RegisterClassEx(
// _In_ const WNDCLASSEX *lpwcx
// );
WinDef.ATOM RegisterClassEx(WinUser.WNDCLASSEX lpwcx);
// HWND WINAPI CreateWindowEx(
// _In_ DWORD dwExStyle,
// _In_opt_ LPCTSTR lpClassName,
// _In_opt_ LPCTSTR lpWindowName,
// _In_ DWORD dwStyle,
// _In_ int x,
// _In_ int y,
// _In_ int nWidth,
// _In_ int nHeight,
// _In_opt_ HWND hWndParent,
// _In_opt_ HMENU hMenu,
// _In_opt_ HINSTANCE hInstance,
// _In_opt_ LPVOID lpParam
// );
WinDef.HWND CreateWindowEx(
int dwExStyle,
String lpClassName,
String lpWindowName,
int dwStyle,
int x,
int y,
int nWidth,
int nHeight,
WinDef.HWND hWndParent,
WinDef.HMENU hMenu,
WinDef.HINSTANCE hInstance,
WinDef.LPVOID lpParam
);
// BOOL WINAPI GetMessage(
// _Out_ LPMSG lpMsg,
// _In_opt_ HWND hWnd,
// _In_ UINT wMsgFilterMin,
// _In_ UINT wMsgFilterMax
// );
boolean GetMessage(WinUser.MSG lpMsg, WinDef.HWND hWnd, int wMsgFilterMin, int wMsgFilterMax);
// LRESULT WINAPI DispatchMessage(
// _In_ const MSG *lpmsg
// );
WinDef.LRESULT DispatchMessage(WinUser.MSG lpmsg);
WinDef.LRESULT DefWindowProc(WinDef.HWND hWnd, int uMsg, WinDef.WPARAM wParam, WinDef.LPARAM lParam);
}
/**
* <pre>
* All Possible events -
* https://msdn.microsoft.com/en-us/library/windows/desktop/ms644927.aspx#system_defined
* https://github.com/tpn/winsdk-10/blob/master/Include/10.0.10240.0/um/WinUser.h
* </pre>
*/
public static class MyWinProc implements WinUser.WindowProc {
private final OutputStream out;
public MyWinProc() {
try {
// this is unsafe because this file will never be closed, anyway it is just for a example
out = new FileOutputStream(new File(System.getProperty("user.home") + File.separator + "shutdown-hook.log"));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
@Override
public WinDef.LRESULT callback(WinDef.HWND hWnd, int uMsg, WinDef.WPARAM wParam, WinDef.LPARAM lParam) {
final String msg = String.format("action=proc-callback, event=%d %n", uMsg);
System.out.print(msg);
try {
out.write(msg.getBytes());
switch (uMsg){
case 0x0016:
out.write("shutdown".getBytes());
break;
case 0x0011:
out.write("logoff".getBytes());
break;
}
out.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
return User32.INSTANCE.DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
}
obs: nur ein Vorschlag, Ihre Anforderungen je denke ich, dass vielleicht kann mehr Sinn macht, wenn man nur einen Hintergrund-Thread statt und tim starten e nach der Zeit tun Sie die Aufgabe, die Sie tun müssen, wenn die Windows blue screen of death oder die Macht weggeht oder jemand nur den Strom abschalten dann werden die Windows-Ereignisse Ihnen nicht helfen. Auf jeden Fall ist Hintergrund Thread-Lösung sehr viel einfacher.
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
Executors.newSingleThreadExecutor().execute(() -> {
while(!Thread.currentThread().isInterrupted()){
System.out.println("do a background stuff");
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {/*I will look at that in the while clause*/}
}
});
System.out.println("doing another stuff");
}
}
Meine Abhängigkeiten
compile group: 'net.java.dev.jna', name: 'jna', version: '4.5.0'
compile group: 'net.java.dev.jna', name: 'jna-platform', version: '4.5.0'
Sehen Sie, wenn https://stackoverflow.com/questions/42598097/using-javafx-application-stop-method-over-shutdownhook hilft (ich habe nicht ein Windows Box verfügbar atm um dies zu testen). –
Aber wenn die Anwendung das System herunterfährt, schließt das System alle Anwendungen, und Sie können Ihre Methoden in 'setOnCloseRequest()' hinzufügen. –
@XlintXms 'setOnCloseRequest()' ist spezifisch für ein Fenster/eine Bühne, nicht für die gesamte Anwendung. –