JavaFX - 如何检测 Windows 注销/关闭请求?

2024-05-04

我有一个应用程序必须在退出时处理一些方法。但是,当用户在没有先关闭我的应用程序的情况下关闭 Windows 时,Windows 会终止该应用程序并且不会运行关闭方法。

如何检测用户何时请求关闭或注销 Windows?我需要运行的方法需要几毫秒才能完成,因此我不一定需要推迟或中断关闭过程。

我已经使用 JNA 来响应机器被锁定/解锁,但是onMachineLogoff()方法似乎也没有捕获关闭请求。


三种不同的场景 https://stackoverflow.com/questions/40825747/close-my-program-before-windows-shutdown当您可以处理关闭和注销事件时。我将重点关注 Windows 应用程序,因为它也适用于控制台应用程序,如果由于某种原因您的应用程序导入 User32 函数,那么控制台句柄将不起作用。

基本上你需要两个函数:

ATOM RegisterClassEx(WNDCLASSEX *lpwcx);

注册类Ex https://msdn.microsoft.com/en-us/library/windows/desktop/ms633587(v=vs.85).aspx创建一种带有与之关联的钩子(即我们的关闭/注销处理程序)的新型窗口。

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
);

创建窗口Ex https://msdn.microsoft.com/en-us/library/windows/desktop/ms632680(v=vs.85).aspx实例化一个新窗口,该窗口有一个关联的事件钩子(通过注册的类),这样Windows将通知关联的钩子所有可能发生的事件 https://msdn.microsoft.com/en-us/library/windows/desktop/ms644927.aspx#system_defined.

这是一个完整的工作示例,只需启动它并注销或关闭计算机,重新启动后,看看%userprofile%\shutdown-hook.log文件它必须通过记录类似的内容来处理这些事件

...
action=proc-callback, event=22 
...

code https://github.com/mageddo/java-native-examples/blob/7ffee35/src/main/java/nativeapi/jna/windows/shutdownhook/Main.java

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:只是一个建议,根据您的要求,我认为如果您只是启动一个后台线程,并且一次又一次地执行您必须执行的任务,那么也许会更有意义,因为如果 Windows 获得蓝屏死机 https://en.wikipedia.org/wiki/Blue_Screen_of_Death或者电源消失或者有人刚刚拔掉电源,那么 Windows 事件将无法帮助您。无论如何,后台线程解决方案相当简单。

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");
    }
}

我的依赖

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'
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaFX - 如何检测 Windows 注销/关闭请求? 的相关文章

  • JavaFx - 线程“JavaFX 应用程序线程”中的无尽异常 java.lang.NullPointerException

    我得到以下异常 甚至无法理解它出现在什么地方 这意味着什么 Exception in thread JavaFX Application Thread java lang NullPointerException at com sun ja
  • 设置默认 JavaFX 对话框的样式

    我正在寻找一种方法来设置默认 JavaFX 对话框的样式 javafx scene control Dialog 我尝试获取 DialogPane 并添加样式表 但它只覆盖了对话框的一小部分 我更喜欢仅使用外部 css 文件设置样式 而不在
  • 从 javaFX 场景拖放到 Windows 资源管理器

    有什么方法可以从 javaFX 场景拖放到 Windows 资源管理器吗 就在这里 您应该使用 onDragDetected 函数来启动拖放事件 并使用 onDragDone 函数在完成拖放后执行您想要的任何操作 这里有一个例子 final
  • JavaFX 中的隐形舞台/场景

    我正在寻找一种隐藏 JavaFX 舞台或场景的方法 现在我知道了 hide 但这行不通 我需要一些仍然保留窗口的东西 但只是使其完全透明 一个很好的比喻是display none and visibility hidden在CSS中 第一个
  • JavaFX 中按下按钮的样式

    我有一个Button in my FXML文件 我在下面给它一个样式CSS button fx background color linear gradient ff5400 be1d00 fx background radius 30 f
  • 尝试使 Tableview 可点击时发生 JavaFX 错误

    我正在尝试使表格视图可单击 它将返回单击的单元格中的文本 尝试在 Netbeans 中编译时收到两个错误 所有代码均取自 示例12 11 单元格编辑的替代解决方案 官方表格视图教程 http docs oracle com javafx 2
  • FXML load() 期间出现 JavaFX IllegalAccessException

    我有一个由以下代码调用的对话框窗口 DialogController是使用模式对话框窗口的辅助类 它主要将控制器引用与其窗口捆绑在一起 void handleServicesEdit ActionEvent event throws IOE
  • 学习 Java Native Access 时出现 com.sun.glass.ui 包错误

    我正在尝试在 JavaFX 项目中使用 Undecorated 阶段 stage initStyle StageStyle UNDECORATED 它是一个模块化的 Gradle 项目 它也是一个多项目构建 https guides gra
  • 使用 PixelWriter 在 JavaFX Canvas 上进行透明绘图

    有谁知道为什么使用drawImage 在Canvas上进行透明度绘制工作得很好 但在PixelWriter上却根本不起作用 我最初认为这可能与画布 上下文上的混合或其他模式 设置有关 但还没有任何运气 我需要每个像素的可变透明度 而不是整个
  • 将两个表视图绑定在一起,以便它们同步滚动

    我想将两个表视图绑定在一起 以便它们同步滚动 我怎么做 我无法找到如何访问表格视图的滚动条 我做了一个CSS hack来将Tableview与外部滚动条绑定 一个滚动条控制两个表格视图 我的想法的概述 创建两个表视图 制作一个垂直滚动条 在
  • 有没有办法设置独立 TableView 列的样式?

    我可以使用 CSS 来设置单元格样式 但如果我只想为一列使用不同的样式 例如使用不同的文本颜色 怎么办 也许我错过了一些东西 你应该使用TableColumn setCellFactory http docs oracle com java
  • 向 Windows 任务栏缩略图添加按钮 JavaFX?

    这个问题已经闲置一年多了 我的问题仍然没有解决方案 我编辑此内容是为了澄清我的问题并引起人们对它的新关注 如果您使用 Windows 您可能知道将程序图标悬停在任务栏上时显示的小预览图像 缩略图 某些程序 例如 Spotify Git 扩展
  • JavaFX 中 ImageView 的顺序转换

    我已经看过了如何在 javafx 2 1 中等待转换结束 https stackoverflow com questions 11188018 how to wait for a transition to end in javafx 2
  • 无法解析符号“javafx.scene.web”

    使用Intellij 2021 3 2 JavaFX版本 11 0 2 1 我正在尝试将 JavaFX WebView 添加到我的应用程序中 我的导入语句无法编译 import javafx scene web 编译错误 java 找不到符
  • 按日期对图表中的 X 轴进行排序 - JavaFX

    如何按日期对折线图 X 轴进行排序 现在我的折线图看起来像这样 我试图剪切日期并将其转换为 int 但现在我不知道该怎么办 datesToCompare addAll LastHoursAndDates keySet dates in St
  • 在 JavaFX 中搜索 TableView 列表

    如何在 TableWie 中查找记录 例如通过 ID 并选择创建的行并将其放在 Java 8 JavaFX 中的屏幕中间 您可以使用以下方式搜索元素 int searchId table getItems stream filter ite
  • JavaFX MediaPlayer - 音乐在 10 秒后停止

    这是代码 就像标题所说的 音乐在10秒后停止 我在vlc或其他程序中正常播放该文件 持续了5分钟多 public void music String bip src data fjordmusic mp3 Media hit new Med
  • 如何在 JavaFX 中连接可观察列表?

    我所说的串联是指获得一个新列表 该列表侦听所有串联部分的更改 方法的目的是什么FXCollections concat ObservableList
  • 如何在 JavaFX 中将 FontAwesome 升级到版本 5

    我有一个使用 FontAwesome 图标的 JavaFX 我想使用新版本 5 但似乎已经不起作用了 这是一个用 Groovy 编写的简单演示应用程序 可与旧版 FontAwesome 一起使用 import javafx applicat
  • JavaFX:将像素写入 PixelWriter 的最快方法

    我正在寻找最快的方式来写入像素javafx scene image Image 写信给BufferedImage的后备数组要快得多 至少在我制作的测试图像上 只花了大约 20 毫秒BufferedImage WritableImage另一方

随机推荐

  • Android 模拟器 x86 HAXM GPU Windows 7 崩溃 BSOD

    我不懂英语 但我会尽力解释 我使用最新版本的 Android SDK 从 AVD Manager 模拟器 intel x86 和 intel HAXM 运行 它工作正常 但是当我启用主机 GPU 时 Windows 7 崩溃 BSOD 这种
  • 确定非空列表条目是否“连续”的 Pythonic 方法

    我正在寻找一种方法来轻松确定列表中所有非 None 项目是否出现在单个连续切片中 我将使用整数作为非 None 项目的示例 例如 列表 None None 1 2 3 None None 满足我对连续整数条目的要求 相比之下 1 2 Non
  • 推进并离开加入

    在教义中我可以 q Doctrine Query create gt from One o gt where t text aaa gt andWhere h text bbb gt leftJoin o Two t gt leftJoin
  • 如何在 VBA 中克隆范围对象

    我正在使用 Excel Visual Basic 编辑器在 VBA 中编写 Excel 宏 我不知道如何复制 克隆范围对象 而不是创建对同一对象的第二个引用 MemberwiseClone 函数似乎不可用 我认为它将针对内置类型实现 我需要
  • 路由器在 Ionic 上导航,并在 ios 上使用角度动画闪烁动画

    我正在使用 angular animations 在 Ionic v4 上的两个页面之间设置页面转换 这一切在 chrome 上都很好用 但在 safari 上却不行 在一个只有两个页面 热切加载 的简单应用程序上 我仍然遇到问题 与我尝试
  • android 录音时可以静音吗

    我想构建一个应用程序 我想在通话中调制声音 我编写了一段代码来记录声音并以不同的音调播放它 现在我想要在通话时使用此功能 我想将通话静音 记录声音然后以不同的音调播放它 如何将通话静音但仍录制音频 此答案可在通话期间使麦克风静音 Boole
  • NetBeans IDE 在“清理和构建”或外部更改时发出异常编译器错误。IDE 无法识别 JPA 生成的静态元模型

    我已经完全厌倦了使用 NetBeans IDE 8 x 目前使用 8 0 1 几个月了 它看起来就像地狱 说真的 当对项目 尤其是 Java EE Web 应用程序 在不同包中包含数百个 Java 类 进行一些外部更改或尝试清洁和构建项目
  • Notepad++ SourceCookifier 插件在大型 C++ 标头上非常慢

    我喜欢在 Notepad 中浏览我的 C 项目 我使用 SourceCookifier 插件来轻松地在大文件的定义之间跳转 但是 如果我加载一个大的 C 头文件 大约 30 000 行 其中有很多 define and typedef里面的
  • User.Identity.GetUserId 是缓存还是每次都从数据库获取?

    我正在使用 ASP Net MVC 5 并且我在我的代码中调用这一行 string userId User Identity GetUserId ASP NET MVC 是否会在每次调用时从表中获取此数据 还是将其缓存 查看 Microso
  • 一次向字符串添加一行

    我有这个程序 可以让你打开一个文件并将其读入一个JTextArea使用以下代码一次性完成所有操作 try String fileContents new Scanner new File fileName useDelimiter Z ne
  • 如何在 WPF 中执行操作之前延迟

    我尝试使用下面的代码在导航到下一个窗口之前延迟 2 秒 但线程首先调用 文本块显示一微秒并进入下一页 我听说调度员会这样做 这是我的片段 tbkLabel Text two mins delay Thread Sleep 2000 Page
  • 如何使用 Ajax 和 Jquery 验证提交表单?

    我正在尝试使用 Ajax 提交一个 from 并使用查询验证插件来验证它 我在下面编写代码
  • 无法解析:com.android.support:recyclerview-v7:28.1.1

    我正在尝试使用 RecyclerView 并添加了这一行implementation com android support recyclerview v7 28 0 0 alpha3 to my build gradle app 但它给出
  • 使用 git-cvsserver 和 CVS 工作副本获取 commitid 或“git描述”

    我有一些自动化工具可以通过以下方式访问 git 存储库cvs and git cvsserver 我希望这些工具能够看到他们签出的内容的提交 ID 这是否记录在CVS元数据目录 None
  • 如何在两个 960.gs 框之间添加垂直线?

    我正在使用 960 gs 网格系统进行设计 在两个盒子之间添加一条细细的分隔垂直线的最佳方法是什么 宽度和颜色应该是可调的 我的计划是定义几个具有绝对位置和背景颜色的 div 类 每个可能的位置对应一个 并使用 JQuery 确保它与周围的
  • C++ 私有和受保护的虚拟方法

    似乎最好将虚拟方法设为私有 以便分离以下两个客户端的接口 1 实例化对象并调用方法的客户端 2 从该类派生并可能想要重写该方法的客户端 简而言之 第一个客户端不需要知道方法是否是虚拟的 他将调用基类公共非虚拟方法 该方法又将调用私有虚拟方法
  • 如何将 char * 转换为 BSTR?

    如何将 char 从 C dll 传递到 VB 这是示例代码 void Cfunc char buffer int len BSTR buf bstr SysAllocString BSTR buffer VBptr VBfunc buf
  • 进行 URL 重写

    当我点击网站上给定条目的评论部分时 URL 如下所示 http www com comments index php submission Portugal 20Crushes 20North 20Korea submissionid 62
  • 运行玩笑测试时,Firebase 在signInAnonymously() 上抛出“auth/network-request-failed”

    我正在使用 firebase 为我的应用程序 使用 create react app 构建 编写一些测试 并且我正在尝试匿名登录我的测试数据库 但认证失败 然而 所有其他 Firebase 操作 CRUD 都工作得很好 我还可以从在浏览器中
  • JavaFX - 如何检测 Windows 注销/关闭请求?

    我有一个应用程序必须在退出时处理一些方法 但是 当用户在没有先关闭我的应用程序的情况下关闭 Windows 时 Windows 会终止该应用程序并且不会运行关闭方法 如何检测用户何时请求关闭或注销 Windows 我需要运行的方法需要几毫秒