如果应用程序打开,Jpackage MSI 升级不会完成

Jpackage MSI upgrade does not complete if application is open

我正在使用 Jpackage 为我们的 java 应用开发 MSI 安装程序。

版本:

openjdk version "17.0.1" 2021-10-19
OpenJDK Runtime Environment Temurin-17.0.1+12 (build 17.0.1+12)
OpenJDK 64-Bit Server VM Temurin-17.0.1+12 (build 17.0.1+12, mixed mode, sharing

jpackage 17.0.1

OS Name:                   Microsoft Windows Server 2019 Datacenter
OS Version:                10.0.17763 N/A Build 17763
OS Manufacturer:           Microsoft Corporation
OS Configuration:          Standalone Server
OS Build Type:             Multiprocessor Free

J包用法:

jpackage --input ./home ^
  --name "Acme Application" ^
  --main-jar app.jar ^
  --main-class org.springframework.boot.loader.JarLauncher ^
  --java-options "-splash:$APPDIR/splash.png" ^
  --java-options -Xmx2g ^
  --icon resources/package.ico ^
  --win-shortcut ^
  --win-menu ^
  --type msi ^
  --app-version %1

升级过程

安装工作正常,一切正常 运行。升级过程在正常情况下也能正常工作。当用户尝试 运行 新的 MSI 包时应用程序仍在 运行ning,MSI 安装程序会提示用户在继续之前关闭应用程序:

选择关闭应用程序并继续会导致应用程序在用户桌面上关闭,但安装程序随后会再次使用相同的对话框提示用户。选择相同的选项(关闭并继续),允许安装程序完成,但随后会警告用户他们需要重新启动。

重新启动后,应用程序版本 1.0.0 似乎仍然是 运行ning。查看前后的jar文件签名,发现安装程序覆盖原文件失败

事件查看器

检查事件查看器,我只看到了一些我感兴趣的东西:

Windows Installer requires a system restart. Product Name: *******. Product Version: 1.0.1. Product Language: 1033. Manufacturer: Unknown. Type of System Restart: 1. Reason for Restart: 0.

The Windows Installer initiated a system restart to complete or continue the configuration of '*******'.

未能停止应用程序

我还注意到应用程序没有完全停止。查看任务管理器,它显示应用程序 运行ning 在用户下,然后移动到后台进程。这使我相信它仍在锁定 jar 文件。应用程序在其他情况下正常停止,所以我不确定这里有什么不同。

我假设我需要解开这个谜,但我不知道为什么应用程序在处理其他所有内容时不响应安装程序的关闭信号。

好吧,我已经做了一些挖掘,这与 JavaFX 的生命周期有关。简单地覆盖 Application.stop 方法不足以正确关闭这些类型的关闭请求。

我的应用程序的两个更改解决了这个问题:

在主阶段onCloseRequest注册一个EventHandler

这里我初始化我的 spring 应用程序并注册事件处理程序以停止应用程序:

@Override
public void start(Stage stage) {
    applicationContext.publishEvent(new StageReadyEvent(stage));
    stage.setOnCloseRequest(event -> stop());
}

确保您在 EventHandler

中调用了 System.exit 在这些情况下

Platform.exit 不足以关闭应用程序:

@Override
public void stop() {
    log.info("Shutting down application...");
    applicationContext.close();
    Platform.exit();
    log.info("Shutdown complete");

    // System.exit is required or the app will move to a background process on uninstall/upgrade
    // events from Windows MSI installer
    System.exit(0);
}