-
Notifications
You must be signed in to change notification settings - Fork 9
rfc: MSIX auto-updater #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,270 @@ | ||
| # MSIX Auto Updater | ||
|
|
||
| - Start Date: 2025-09-16 | ||
| - RFC PR: [electron/rfcs#21](https://github.com/electron/rfcs/pull/21) | ||
| - Electron Issues: | ||
| - [electron/forge#3976](https://github.com/electron/forge/issues/3976) | ||
| - [electron/electron#17722](https://github.com/electron/electron/issues/17722) | ||
| - Reference Implementation: [electron/electron#0000](https://github.com/electron/electron/pull/0000) | ||
| - Status: **Proposed** | ||
|
|
||
| ## Summary | ||
|
|
||
| [MSIX](https://learn.microsoft.com/en-us/windows/msix/overview) is an app package format developed | ||
| by Microsoft for Windows. It is designed to replace previous generations of installer formats such | ||
| as AppX, MSI, and ClickOnce. | ||
|
|
||
| This RFC proposes adding first-class support for MSIX packages in Electron by supporting its native | ||
| auto-update API with Electron's [`autoUpdater`](https://github.com/electron/electron/blob/main/shell/browser/auto_updater.h) module. | ||
|
|
||
| This change would reroute `autoUpdater` requests for MSIX-packaged apps away from Electron's existing [Squirrel.Windows](https://github.com/Squirrel/Squirrel.Windows) implementation and into a new code path that calls the MSIX update APIs. | ||
|
|
||
| ## Motivation | ||
|
|
||
| ### Installers in Electron | ||
|
|
||
| There are currently three primary app package formats for Windows supported by Electron: | ||
|
|
||
| - Squirrel.Windows is the installer created by | ||
| [`electron-winstaller`](https://github.com/electron/windows-installer). It supports automatic updates | ||
| via Electron's `autoUpdater` module and is designed for seamless installation with | ||
| minimal user interaction. The main problem with Squirrel.Windows is that the project is | ||
| functionally unmaintained, with the last release being | ||
| [v2.0.1](https://github.com/Squirrel/Squirrel.Windows/releases/tag/2.0.1) in 2020. | ||
| - [Windows Installer](https://learn.microsoft.com/en-us/windows/win32/msi/windows-installer-portal) | ||
| (also known as Microsoft Installer or MSI) is the prevailing installer enterprise environments. | ||
| Out of the box, MSI does not provide any auto-updating capabilities and is often deployed with administrative rights which would make an auto-updater implementation challenging. MSI installers can be | ||
| generated by [`electron-wix-msi`](https://github.com/electron-userland/electron-wix-msi). | ||
| - AppX is a format for the older [Universal Windows Platform (UWP)](https://learn.microsoft.com/en-us/windows/uwp/get-started/universal-application-platform-guide). UWP apps are generally distributed on the | ||
| [Microsoft Store](https://apps.microsoft.com/). AppX packages can be generated with | ||
| [`electron-windows-store`](https://github.com/electron-userland/electron-windows-store). | ||
|
|
||
| ### Why MSIX? | ||
|
|
||
| Microsoft's newer MSIX packaging format promises a modern approach to application deployment that aims | ||
| to supersede all currently-supported installers. It combines the auto-updating of Squirrel.Windows, | ||
| the enterprise configuration options of MSI, and the ability to distribute to the Microsoft Store | ||
| from AppX. | ||
|
|
||
| Key features include network bandwidth and disk space optimization, clean uninstallation, | ||
| and support for tools like Microsoft Endpoint Configuration Manager, Microsoft Intune, and | ||
| Deployment Image Servicing and Management (DISM.exe). It also supports MSIX App Attach for virtualized environments, AppInstaller for self-hosted deployment and updates, and PowerShell commands for management. | ||
|
|
||
| It achieves a 99.96% success rate across millions of installations, as [reported by Microsoft](https://learn.microsoft.com/en-us/windows/msix/overview#:~:text=MSIX%20provides%20a%20reliable%20install%20boasting%20a%2099.96%25%20success%20rate%20over%20millions%20of%20installs%20with%20a%20guaranteed%20uninstall). | ||
|
|
||
| MSIX enables auto-updating through Windows OS APIs, unlike MSI, which lacks this feature, or Squirrel.Windows, which requires a custom updater to be maintained and distributed. | ||
|
|
||
| For details on supported features by OS version, see the [MSIX features and supported platforms](https://learn.microsoft.com/en-us/windows/msix/supported-platforms?view=winrt-26100.) | ||
| page in the Microsoft developer documentation. | ||
|
|
||
| ## Guide-level explanation | ||
|
|
||
| MSIX installers can already be generated through the [`electron-windows-msix`](https://github.com/bitdisaster/electron-windows-msix) npm package. | ||
| However, they currently do not integrate with Electron's `autoUpdater` module. | ||
|
|
||
| This RFC aims to provide a native auto-updating experience for MSIX that is completely | ||
| transparent to the user-facing `autoUpdater` API. Under the hood, Electron will detect | ||
| the type of package being used and call the corresponding system API accordingly. | ||
|
|
||
| We propose that the MSIX updater feed follows the Squirrel.Mac JSON format to standardize | ||
| update server responses across platforms. | ||
|
|
||
| ## Reference-level explanation | ||
|
|
||
| ### Overview | ||
|
|
||
| Electron's [autoUpdater](https://www.electronjs.org/docs/latest/api/auto-updater) module supports macOS and Windows. Electron contains an implementation per-platform where the Windows updater assumes the use of Squirrel. | ||
|
|
||
| ```js | ||
| // lib/browser/api/auto-updater.ts | ||
| if (process.platform === "win32") { | ||
| module.exports = require("./auto-updater/auto-updater-win"); | ||
| } else { | ||
| module.exports = require("./auto-updater/auto-updater-native"); | ||
| } | ||
| ``` | ||
|
|
||
| To introduce MSIX auto updating, Electron will provide a new updater implementation when a **Windows packaged app** is detected. | ||
|
|
||
| > [!IMPORTANT] | ||
| > This RFC refers to "Windows packaged apps" in the sense of Windows apps that have a Package Identity, rather than "packaged" in | ||
| > the Electron sense. See the Microsoft's [Deployment Overview](https://learn.microsoft.com/en-us/windows/apps/package-and-deploy/) | ||
| > documentation for more information. | ||
|
|
||
| ### Windows packaged apps | ||
|
|
||
| Updating an application deployed with MSIX requires knowing about its packaged app identity. APIs will be needed to gather this information under a `windowsPackagedApp` namespace. | ||
|
|
||
| This will allow the packaged app to know its ID for updating and whether its | ||
| distributed as standalone or from the Microsoft Store. | ||
|
|
||
| ```ts | ||
| /** | ||
| * Info about an application package. | ||
| * @see https://learn.microsoft.com/en-us/uwp/api/windows.applicationmodel.package?view=winrt-22621 | ||
| */ | ||
| interface WindowsPackagedAppInfo { | ||
| /** | ||
| * 'FullName' ID. | ||
| * e.g. 91750D7E.Slack_4.38.65535.0_arm64__8she8kybcnzg4 | ||
| */ | ||
| id: string; | ||
| /** | ||
| * Family name which uniquely identifies the package independent of its version. | ||
| * e.g. 91750D7E.Slack_8she8kybcnzg4 | ||
| */ | ||
| familyName: string; | ||
| /** | ||
| * Whether the package is installed in development mode. | ||
| */ | ||
| developmentMode: boolean; | ||
| /** | ||
| * Kind of signature. | ||
| * Can be 'developer', 'enterprise', 'none', 'store', or 'system'. | ||
| * @see https://learn.microsoft.com/en-us/uwp/api/windows.applicationmodel.packagesignaturekind?view=winrt-22621 | ||
| */ | ||
| signatureKind: string; | ||
| /** | ||
| * URI to the .appinstaller file associated with the current app. | ||
| * Only present if the app is installed using this method. | ||
| */ | ||
| appInstallerUri?: string; | ||
| } | ||
|
|
||
| interface WindowsPackagedApp { | ||
| /** | ||
| * Get info about the current application package. | ||
| * | ||
| * Throws if the current application has no packaged identity. | ||
| */ | ||
| getPackagedAppInfo(): WindowsPackagedAppInfo; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this be exposed in the
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes we should expose that API. For many purposes, developers will need to know at runtime of an app whether its MSIX packaged. For example, if you want to check whether Notifications are enabled for your app, you need to call the Window API for that differently. If you are not an MSIX packager app, you have to pass in the AUMID. If you are a MSIX packaged App then you shouldn't pass the AUMID, otherwise the API call fails. So there will be always slight differences in MSIX packaged apps. |
||
| } | ||
| ``` | ||
|
|
||
| ### Performing updates | ||
|
|
||
| Electron apps expect auto updates to be performed with the following procedure: | ||
|
|
||
| 1. Request update info from web server. | ||
| 2. Download update in the background. | ||
| 3. Apply update on next app launch. | ||
|
|
||
| To meet these requirements, we'll need to invoke methods on the [WinRT PackageManager class.](https://learn.microsoft.com/en-us/uwp/api/windows.management.deployment.packagemanager?view=winrt-22621) | ||
|
|
||
| ```ts | ||
| /** | ||
| * Options to customize the behavior of MSIX updates. | ||
| * @see https://learn.microsoft.com/en-us/uwp/api/windows.management.deployment.addpackageoptions?view=winrt-22621 | ||
| */ | ||
| type UpdatePackageOptions = { | ||
| /** | ||
| * Callback with percentage completition over the entire course of the | ||
| * deployment operation. | ||
| * @param percentage Installation percentage | ||
| */ | ||
| onprogress?: (percentage: number) => void; | ||
| }; | ||
|
|
||
| interface WindowsPackagedApp { | ||
| /** | ||
| * Download MSIX package to update to. Defer registering update until app | ||
| * restarts. | ||
| * @param packageUri A URL path to an MSIX package. | ||
| * @see https://learn.microsoft.com/en-us/uwp/api/windows.management.deployment.packagemanager.addpackagebyuriasync?view=winrt-26100 | ||
| */ | ||
| updatePackage( | ||
| packageUri: string, | ||
| options?: UpdatePackageOptions | ||
| ): Promise<void>; | ||
|
|
||
| /** | ||
| * Deploy downloaded package for updating. Terminates the application to | ||
| * proceed with updates. | ||
| * @see https://learn.microsoft.com/en-us/uwp/api/windows.management.deployment.packagemanager.registerpackagebyfamilynameasync?view=winrt-26100 | ||
| */ | ||
| deployPackage(): Promise<void>; | ||
| } | ||
| ``` | ||
|
|
||
| ### Determining update availability | ||
|
|
||
| Electron has historically used Squirrel updater on both Mac and Windows. Although they share the same name, their implementations and [update mechanisms are different.](https://www.electronjs.org/docs/latest/tutorial/updates#update-server-specification) | ||
|
|
||
| - Squirrel for Windows: fetches `RELEASES` file | ||
| - Squirrel for Mac: fetches JSON document | ||
|
|
||
| With the introduction of a new updater, we should take this opportunity to | ||
| converge these designs. The MSIX updater proposes to use the Mac's JSON update | ||
| file format. | ||
|
|
||
| ```json | ||
| { | ||
| "url": "https://your-static.storage/your-app-1.2.3-windows.msix", | ||
| "name": "1.2.3", | ||
| "notes": "Update for MSIX packaged app", | ||
| "pub_date": "2025-07-22T18:59:52.022Z" | ||
| } | ||
| ``` | ||
|
|
||
| ## Drawbacks | ||
|
|
||
| * The MSIX format has some limitation over older formats like MSI. Installation of device drivers for example are not possible. That being said, capabilities have been constantly expanded with each Windows version. See [feature-support](https://learn.microsoft.com/en-us/windows/msix/supported-platforms#msix-feature-support) for details. | ||
| * By default, MSIX packaged apps access to the registry and file systems are virtualized. Therefore it is not possible for an app to communicate changes to other apps via registry/filesystem or to make permanent modifications. If this is not the desired behavior than manifest declarations can be made to poke holes into the virtualization starting with Windows; Build 18362. See [MSIX virtualization](https://learn.microsoft.com/en-us/windows/msix/desktop/flexible-virtualization) for details. | ||
| * Using the MSIX updater capabilities on Windows simplifies maintenance by eliminating the need for a custom auto-updater like Squirrel.Windows. However, this approach means we lose control if issues arise and must rely on Microsoft to deliver timely fixes. | ||
|
|
||
| ## Rationale and alternatives | ||
|
|
||
| ### Why This Design? | ||
|
|
||
| * Native Integration: Uses Windows’ PackageManager APIs, eliminating maintenance of custom updaters like Squirrel.Windows and ensuring compatibility with Microsoft’s ecosystem (e.g., Intune, Endpoint Configuration Manager). | ||
| * Unified API: Maintains the existing autoUpdater API, transparently routing MSIX packages to native APIs, simplifying developer experience. | ||
| * Cross-Platform Consistency: Adopts Squirrel.Mac’s JSON update format, aligning Windows and macOS update mechanisms. | ||
| * Proven Reliability: MSIX’s 99.96% install success rate and Slack’s greater than 99% update success rate across a substantial install base match Squirrel.Windows’ performance without custom maintenance. | ||
| * Future-Proof: MSIX is Microsoft’s modern packaging format, replacing MSI, AppX, and ClickOnce, aligning Electron with Windows’ long-term strategy. | ||
|
|
||
| ### Alternatives Considered | ||
|
|
||
| * Status Quo (No MSIX Auto-Updating): Keep reliance on unmaintained Squirrel.Windows (last release 2020). This also means no auto-update support for MSIX as Squirrel.Windows does not support MSIX updating, risking falling behind as MSIX adoption grows. | ||
| * Node Module for MSIX Updater: Distributing the updater as a native module, as Slack does, fragments the ecosystem, requiring developers to integrate and maintain it separately. Integration into Electron ensures consistency and distributes maintenance burden to the community. | ||
| * Other Auto-Updating Technologies: No other solution offers native OS support for auto-updating. Any alternatives would require a custom implementation similar to Windows.Squirrel, carrying the the same disadvantages. | ||
|
|
||
|
|
||
| ## Prior art | ||
|
|
||
| The code for this RFC has already been implemented in [Slack Desktop's MSIX implementation](https://slack.com/downloads/windows). | ||
| This implementation exists in three parts: | ||
| * [bitdisaster/electron-windows-msix](electron-windows-msix) for MSIX installer creation. | ||
| * A custom [Electron Forge](http://electronforge.io/) maker that wraps around the above package. | ||
| * A native Node.js module that handles the auto-update process. | ||
|
|
||
| At Slack, we have been deploying MSIX builds to Windows customers for the past year with over 1.4 million installations, and have seen it successfully | ||
| replace the use-cases for Squirrel.Windows, WiX MSI, and AppX. The auto-updater delivers consistent update success rate of over 99%, comparable to Squirrel.Windows. | ||
|
|
||
| ## Unresolved questions | ||
|
|
||
| With auto-updating implemented, MSIX makes a compelling case to replace all other installers. It supports machine-wide deployments (previously handled by MSI), store deployments (same as AppX), and auto-updates (currently managed by Squirrel.Windows). However, there is no generalized migration strategy that could be implemented as part of the auto-updating process. A naive migration strategy could be implemented with following steps: | ||
| * install MSIX in parallel | ||
| * on app exit, call Squirrel uninstaller | ||
| * cleanup of potential artifacts like shortcuts and pinned items | ||
| * launch MSIX | ||
|
|
||
| However, each app might have nuances that go beyond these general steps and have to implement migration code tailored to their specific install footprint. | ||
| Regarding user data, MSIX seamlessly handles data stored in `%APPDATA%`, accessing it even without disabling virtualization. If a data need to be accessed in other locations then consider exempting those locations using [virtualization modifications](https://learn.microsoft.com/en-us/windows/msix/desktop/flexible-virtualization). | ||
|
|
||
| ## Future possibilities | ||
|
|
||
| ### .appinstaller auto-updater | ||
|
|
||
| [.appinstaller files](https://learn.microsoft.com/en-us/windows/msix/app-installer/app-installer-file-overview) are another method of deploying MSIX apps. It has its own set of native | ||
| Windows APIs related to update availability and deployment. | ||
|
|
||
| `WindowsPackagedAppInfo['appInstallerUri']` can be used to detect its usage. If detected, Electron can | ||
| choose to use an alternate updater implementation. | ||
|
|
||
| ### Microsoft store auto-updater | ||
|
|
||
| Similary, [Microsoft Store APIs](https://learn.microsoft.com/en-us/windows/msix/store-developer-package-update) are available in Windows. | ||
|
|
||
| `WindowsPackagedAppInfo['signatureKind'] === 'store'` can be used to detect an | ||
| MSIX app deployed from the Microsoft Store. If detected, an MS store-specific | ||
| updater can be used. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these values queried using Windows APIs? Might be worth linking to the APIs that will be used to gather this info.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! This is the API that gives the info https://learn.microsoft.com/en-us/uwp/api/windows.applicationmodel.package.current?view=winrt-26100