Skip to content

fix(msi): forward the Windows installer settings to electron-builder - #629

Merged
kdroidFilter merged 1 commit into
NucleusFramework:mainfrom
takke:fix/msi-windows-installer-options
Aug 31, 2026
Merged

fix(msi): forward the Windows installer settings to electron-builder#629
kdroidFilter merged 1 commit into
NucleusFramework:mainfrom
takke:fix/msi-windows-installer-options

Conversation

@takke

@takke takke commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Problem

The MSI target forwards only upgradeCode and perMachine to electron-builder, so every other
Windows installer setting falls back to an electron-builder default. Projects that migrated from
jpackage-based packaging silently lose three behaviours:

Setting Before (jpackage) Now (electron-builder MSI)
windows.menuGroup --win-menu-group → shortcut in a start menu folder ignored → shortcut lands in the start menu root
installer UI welcome / progress / finish pages oneClick defaults to true → installs with no UI at all
after install nothing runAfterFinish defaults to true → the app is launched

windows { menuGroup / menu / shortcut / dirChooser } are still read by AbstractJPackageTask,
but TargetFormat.Msi is PackagingBackend.ELECTRON_BUILDER, so nothing in that block reaches
the MSI. There is also no way to set these from a build script, since the electron-builder config
is generated from the DSL inside the task and no user config is merged.

Comparing the MSI tables of the same app built before and after the migration:

before: Shortcut          → dir6433… | ProgramMenuFolder | AppName   (start menu folder)
        InstallUISequence → WelcomeDlg / ProgressDlg / ExitDialog …
after:  Shortcut          → startMenuShortcut | ProgramMenuFolder | AppName   (root)
        InstallUISequence → CostInitialize / ExecuteAction only        (no dialogs)

Fix

Add the remaining CommonWindowsInstallerConfiguration options to MsiSettings and emit them:

windows {
  menuGroup = "MyApp"          // already existed; now honored by the MSI target too
  msi {
    perMachine = false
    oneClick = false           // show the installer wizard
    runAfterFinish = false     // don't launch the app when the installer finishes
  }
}
  • Every new option defaults to the electron-builder default, so generated MSIs are unchanged
    unless a project sets one
    — with one intended exception: windows.menuGroup now acts as the
    default for msi.menuCategory, which is the jpackage-era name for the same concept. Projects
    that declared a menu group get their start menu folder back; projects that never set it are
    unaffected (menuCategory stays unset and nothing is emitted).
  • windows.menu / windows.shortcut are deliberately not mapped. Their jpackage defaults
    (false) are the opposite of electron-builder's (true), so mapping them would silently drop
    shortcuts for projects that are happy with today's output. msi.createStartMenuShortcut /
    msi.createDesktopShortcut give explicit control instead.
  • Only the MSI target is touched. NsisSettings already exposes oneClick / runAfterFinish /
    createStartMenuShortcut / createDesktopShortcut; it is missing menuCategory and
    shortcutName, which I'm happy to add in a follow-up if you want the two targets aligned.

Verified against electron-builder's MsiTarget.ts:
menuCategory emits <Directory Id="AppProgramMenuDir" Name="ProgramMenuFolder:\<category>\"/>
and anchors startMenuShortcut there (plus a RemoveFolder on uninstall), oneClick === false
adds -ext WixUIExtension to the light args, and runAfterFinish drives isRunAfterFinish in the
WiX template.

Also verified end to end: I published the patched plugin to Maven Local and rebuilt the same app
with menuGroup plus msi { oneClick = false; runAfterFinish = false }. The MSI tables come out
as expected, and installing it behaves like the jpackage-era package again:

before this PR after
Shortcut startMenuShortcut | ProgramMenuFolder startMenuShortcut | AppProgramMenuDir (folder ProgramMenuFolder\ZonePane)
InstallUISequence Cost*/ExecuteAction only (no UI) WelcomeDlg / ProgressDlg / ExitDialog / MaintenanceWelcomeDlg / ResumeDlg
CustomAction runAfterFinish | 210 | mainExecutable (absent)
UpgradeCode / per-user unchanged unchanged (MSIINSTALLPERUSER=1, same UpgradeCode)

One observable side effect of oneClick = false, inherent to electron-builder's template: the
assisted installer nests the install directory one level deeper
(…\Programs\<app>…\Programs\<company>\<app>), same as it does for NSIS assisted installs.

Tests

  • ElectronBuilderMsiConfigTest (new, 5 cases): defaults are unchanged, each option is forwarded,
    windows.menuGroup is used as the menu category, an explicit msi.menuCategory wins over it,
    and the NSIS target is unaffected.
  • MsiSettingsTest: added a defaults case for the new options.

generateWindowsConfig is now internal so the rendered YAML can be asserted, matching
generateLinuxConfig which is already internal for the same reason.

🤖 Generated with Claude Code

The MSI target only passed upgradeCode and perMachine to
electron-builder, so every other Windows installer setting fell back to
an electron-builder default: windows.menuGroup was ignored and the
shortcut landed in the start menu root, oneClick defaulted to true so
the installer ran without showing any UI, and runAfterFinish defaulted
to true so the app was launched as soon as the install finished.
Projects migrating from jpackage-based packaging lost all three
silently, with no way to set them from a build script.

Add the remaining CommonWindowsInstallerConfiguration options to
MsiSettings and emit them. Each defaults to the electron-builder
default so generated MSIs are unchanged unless a project opts in,
except that windows.menuGroup - the jpackage-era name for the same
concept - now acts as the default for msi.menuCategory, restoring the
start menu folder for projects that already declare one.

windows.menu / windows.shortcut are deliberately not mapped: their
jpackage defaults (false) are the opposite of electron-builder's
(true), so mapping them would silently drop shortcuts from MSIs that
are fine today. msi.createStartMenuShortcut / createDesktopShortcut
give explicit control instead.

generateWindowsConfig becomes internal so the rendered YAML can be
asserted in unit tests, matching generateLinuxConfig which is already
internal for the same reason.
@kdroidFilter

Copy link
Copy Markdown
Collaborator

Thank you very much, great! even though I strongly advise using the nsis format and not msi which is deprecated

@kdroidFilter
kdroidFilter merged commit 6f56231 into NucleusFramework:main Aug 31, 2026
23 checks passed
kdroidFilter pushed a commit that referenced this pull request Aug 31, 2026
Follow-up to #629. The NSIS targets already expose most installer
settings, but not menuCategory / shortcutName, so a start menu group
could not be declared at all: the shortcut always landed in the start
menu root. This blocked projects that are migrating their MSI packaging
to the recommended NSIS format while keeping the start menu folder
they had under jpackage.

Add the two remaining CommonWindowsInstallerConfiguration options to
NsisSettings and emit them for nsis and nsis-web. Both default to null
(nothing emitted), so generated installers are unchanged unless a
project opts in - with the same intended exception as the MSI target:
windows.menuGroup, the jpackage-era name for the same concept, acts as
the default for nsis.menuCategory.

The "nsis target is unaffected by the msi settings" test asserted that
menuCategory never appears for NSIS; it now asserts the actual concern,
that msi {} values do not leak into the nsis block.
kdroidFilter added a commit that referenced this pull request Sep 1, 2026
Brings the 2.6 line up to date with the released one (#629 MSI installer
options, #630 NSIS menu category, #632 clean-frame present skip, #633
alwaysOnTop stickiness).

Conflict: `nucleus_tao_windows_deco.c` — 2.6's ClearType pixel-geometry probe
and main's #631 topmost helpers were appended at the same spot. Both kept.

Verified on Windows: rebuilt natives, `check` on decorated-window-tao and
nucleus-application, headful suite 27 run / 0 failed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants