Skip to content

Commit 9f823ff

Browse files
committed
msix auto-updater RFC
1 parent d89000c commit 9f823ff

File tree

1 file changed

+296
-0
lines changed

1 file changed

+296
-0
lines changed

text/0021-msix-auto-updater.md

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
# MSIX Auto Updater
2+
3+
- Start Date: 2025-09-16
4+
- RFC PR: [electron/rfcs#21](https://github.com/electron/rfcs/pull/21)
5+
- Electron Issues:
6+
- [electron/forge#3976](https://github.com/electron/forge/issues/3976)
7+
- [electron/electron#17722](https://github.com/electron/electron/issues/17722)
8+
- Reference Implementation: [electron/electron#0000](https://github.com/electron/electron/pull/0000)
9+
- Status: **Proposed**
10+
11+
## Summary
12+
13+
[MSIX](https://learn.microsoft.com/en-us/windows/msix/overview) is an app package format developed
14+
by Microsoft for Windows. It is designed to replace previous generations of installer formats such
15+
as AppX, MSI, and ClickOnce.
16+
17+
This RFC proposes adding first-class support for MSIX packages in Electron by supporting its native
18+
auto-update API with Electron's [`autoUpdater`](https://github.com/electron/electron/blob/main/shell/browser/auto_updater.h) module.
19+
20+
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.
21+
22+
## Motivation
23+
24+
### Installers in Electron
25+
26+
There are currently three primary app package formats for Windows supported by Electron:
27+
28+
- Squirrel.Windows is the installer created by
29+
[`electron-winstaller`](https://github.com/electron/windows-installer). It supports automatic updates
30+
via Electron's `autoUpdater` module and is designed for seamless installation with
31+
minimal user interaction. The main problem with Squirrel.Windows is that the project is
32+
functionally unmaintained, with the last release being
33+
[v2.0.1](https://github.com/Squirrel/Squirrel.Windows/releases/tag/2.0.1) in 2020.
34+
- [Windows Installer](https://learn.microsoft.com/en-us/windows/win32/msi/windows-installer-portal)
35+
(also known as Microsoft Installer or MSI) is the prevailing installer enterprise environments.
36+
Out of the box, MSI does not provide any auto-updating capabilities and is often dpelpoyed with administrative rights which would make an auto-updater implementation challenging. MSI installers can be
37+
generated by [`electron-wix-msi`](https://github.com/electron-userland/electron-wix-msi).
38+
- 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
39+
[Microsoft Store](https://apps.microsoft.com/). AppX packages can be generated with
40+
[`electron-windows-store`](https://github.com/electron-userland/electron-windows-store).
41+
42+
### Why MSIX?
43+
44+
Microsoft's newer MSIX packaging format promises a modern approach to application deployment that aims
45+
to supersede all currently-supported installers. It combines the auto-updating of Squirrel.Windows,
46+
the enterprise configuration options of MSI, and the ability to distribute to the Microsoft Store
47+
from AppX.
48+
49+
Key features include network bandwidth and disk space optimization, clean uninstallation,
50+
and support for tools like Microsoft Endpoint Configuration Manager, Microsoft Intune, and
51+
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.
52+
53+
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).
54+
55+
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.
56+
57+
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.)
58+
page in the Microsoft developer documentation.
59+
60+
## Guide-level explanation
61+
62+
MSIX installers can already be generated through the [`electron-windows-msix`](https://github.com/bitdisaster/electron-windows-msix) npm package.
63+
However, they currently do not integrate with Electron's `autoUpdater` module.
64+
65+
This RFC aims to provide a native auto-updating experience for MSIX that is completely
66+
transparent to the user-facing `autoUpdater` API. Under the hood, Electron will detect
67+
the type of package being used and call the corresponding system API accordingly.
68+
69+
We propose that the MSIX updater feed follows the Squirrel.Mac JSON format to standardize
70+
update server responses across platforms.
71+
72+
## Reference-level explanation
73+
74+
<!--
75+
- lib/browser/api/auto-updater/msix-update-win.ts
76+
- use when packaged app is detected
77+
78+
- process changes
79+
- deprecate process.winstore
80+
- process.windowsPackagedApp
81+
- process.microsoftStore
82+
- getPackageInfo()
83+
- registerPackage()
84+
- updatePackage()
85+
- registerAppRestart()
86+
87+
- use macos squirrel format
88+
- same updater backend for mac and windows now
89+
90+
- .appinstaller file support
91+
- can follow after initial impl
92+
- lib/browser/api/auto-updater/appinstaller-update-win.ts
93+
- https://learn.microsoft.com/en-us/windows/msix/app-installer/app-installer-file-overview
94+
95+
- microsoft store updates
96+
- lib/browser/api/auto-updater/microsoft-store-update-win.ts
97+
- https://learn.microsoft.com/en-us/windows/msix/store-developer-package-update
98+
-->
99+
100+
### Overview
101+
102+
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.
103+
104+
```js
105+
// lib/browser/api/auto-updater.ts
106+
if (process.platform === "win32") {
107+
module.exports = require("./auto-updater/auto-updater-win");
108+
} else {
109+
module.exports = require("./auto-updater/auto-updater-native");
110+
}
111+
```
112+
113+
To introduce MSIX auto updating, Electron will provide a new updater implementation when a **Windows packaged app** is detected.
114+
115+
> [!IMPORTANT]
116+
> This RFC refers to "Windows packaged apps" in the sense of Windows apps that have a Package Identity, rather than "packaged" in
117+
> the Electron sense. See the Microsoft's [Deployment Overview](https://learn.microsoft.com/en-us/windows/apps/package-and-deploy/)
118+
> documentation for more information.
119+
120+
### Windows packaged apps
121+
122+
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.
123+
124+
This will allow the packaged app to know its ID for updating and whether its
125+
distributed as standalone or from the Microsoft Store.
126+
127+
```ts
128+
/**
129+
* Info about an application package.
130+
* @see https://learn.microsoft.com/en-us/uwp/api/windows.applicationmodel.package?view=winrt-22621
131+
*/
132+
interface WindowsPackagedAppInfo {
133+
/**
134+
* 'FullName' ID.
135+
* e.g. 91750D7E.Slack_4.38.65535.0_arm64__8she8kybcnzg4
136+
*/
137+
id: string;
138+
/**
139+
* Family name which uniquely identifies the package independent of its version.
140+
* e.g. 91750D7E.Slack_8she8kybcnzg4
141+
*/
142+
familyName: string;
143+
/**
144+
* Whether the package is installed in development mode.
145+
*/
146+
developmentMode: boolean;
147+
/**
148+
* Kind of signature.
149+
* Can be 'developer', 'enterprise', 'none', 'store', or 'system'.
150+
* @see https://learn.microsoft.com/en-us/uwp/api/windows.applicationmodel.packagesignaturekind?view=winrt-22621
151+
*/
152+
signatureKind: string;
153+
/**
154+
* URI to the .appinstaller file associated with the current app.
155+
* Only present if the app is installed using this method.
156+
*/
157+
appInstallerUri?: string;
158+
}
159+
160+
interface WindowsPackagedApp {
161+
/**
162+
* Get info about the current application package.
163+
*
164+
* Throws if the current application has no packaged identity.
165+
*/
166+
getPackagedAppInfo(): WindowsPackagedAppInfo;
167+
}
168+
```
169+
170+
### Performing updates
171+
172+
Electron apps expect auto updates to be performed with the following procedure:
173+
174+
1. Request update info from web server.
175+
2. Download update in the background.
176+
3. Apply update on next app launch.
177+
178+
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)
179+
180+
```ts
181+
/**
182+
* Options to customize the behavior of MSIX updates.
183+
* @see https://learn.microsoft.com/en-us/uwp/api/windows.management.deployment.addpackageoptions?view=winrt-22621
184+
*/
185+
type UpdatePackageOptions = {
186+
/**
187+
* Callback with percentage completition over the entire course of the
188+
* deployment operation.
189+
* @param percentage Installation percentage
190+
*/
191+
onprogress?: (percentage: number) => void;
192+
};
193+
194+
interface WindowsPackagedApp {
195+
/**
196+
* Download MSIX package to update to. Defer registering update until app
197+
* restarts.
198+
* @param packageUri A URL path to an MSIX package.
199+
* @see https://learn.microsoft.com/en-us/uwp/api/windows.management.deployment.packagemanager.addpackagebyuriasync?view=winrt-26100
200+
*/
201+
updatePackage(
202+
packageUri: string,
203+
options?: UpdatePackageOptions
204+
): Promise<void>;
205+
206+
/**
207+
* Deploy downloaded package for updating. Terminates the application to
208+
* proceed with updates.
209+
* @see https://learn.microsoft.com/en-us/uwp/api/windows.management.deployment.packagemanager.registerpackagebyfamilynameasync?view=winrt-26100
210+
*/
211+
deployPackage(): Promise<void>;
212+
}
213+
```
214+
215+
### Determining update availability
216+
217+
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)
218+
219+
- Squirrel for Windows: fetches `RELEASES` file
220+
- Squirrel for Mac: fetches JSON document
221+
222+
With the introduction of a new updater, we should take this opportunity to
223+
converge these designs. The MSIX updater proposes to use the Mac's JSON update
224+
file format.
225+
226+
```json
227+
{
228+
"url": "https://your-static.storage/your-app-1.2.3-windows.msix",
229+
"name": "1.2.3",
230+
"notes": "Update for MSIX packaged app",
231+
"pub_date": "2025-07-22T18:59:52.022Z"
232+
}
233+
```
234+
235+
## Drawbacks
236+
237+
* 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.
238+
* 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.
239+
* 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.
240+
241+
## Rationale and alternatives
242+
243+
### Why This Design?
244+
245+
* 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).
246+
* Unified API: Maintains the existing autoUpdater API, transparently routing MSIX packages to native APIs, simplifying developer experience.
247+
* Cross-Platform Consistency: Adopts Squirrel.Mac’s JSON update format, aligning Windows and macOS update mechanisms.
248+
* 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.
249+
* Future-Proof: MSIX is Microsoft’s modern packaging format, replacing MSI, AppX, and ClickOnce, aligning Electron with Windows’ long-term strategy.
250+
251+
### Alternatives Considered
252+
253+
* 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.
254+
* 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.
255+
* 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.
256+
257+
258+
## Prior art
259+
260+
The code for this RFC has already been implemented in [Slack Desktop's MSIX implementation](https://slack.com/downloads/windows).
261+
This implementation exists in three parts:
262+
* [bitdisaster/electron-windows-msix](electron-windows-msix) for MSIX installer creation.
263+
* A custom [Electron Forge](http://electronforge.io/) maker that wraps around the above package.
264+
* A native Node.js module that handles the auto-update process.
265+
266+
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
267+
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.
268+
269+
## Unresolved questions
270+
271+
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:
272+
* install MSIX in parallel
273+
* on app exit, call Squirrel uninstaller
274+
* cleanup of potential artifacts like shortcuts and pinned items
275+
* launch MSIX
276+
277+
However, each app might have nuances that go beyond these general steps and have to implement migration code tailored to their specific install footprint.
278+
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).
279+
280+
## Future possibilities
281+
282+
### .appinstaller auto-updater
283+
284+
[.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
285+
Windows APIs related to update availability and deployment.
286+
287+
`WindowsPackagedAppInfo['appInstallerUri']` can be used to detect its usage. If detected, Electron can
288+
choose to use an alternate updater implementation.
289+
290+
### Microsoft store auto-updater
291+
292+
Similary, [Microsoft Store APIs](https://learn.microsoft.com/en-us/windows/msix/store-developer-package-update) are available in Windows.
293+
294+
`WindowsPackagedAppInfo['signatureKind'] === 'store'` can be used to detect an
295+
MSIX app deployed from the Microsoft Store. If detected, an MS store-specific
296+
updater can be used.

0 commit comments

Comments
 (0)