fix(updater): check ShellExecuteW results (#3516)

* fix(updater): check `ShellExecuteW` results

* document the exit on windows
This commit is contained in:
Tony
2026-07-27 16:38:50 +08:00
committed by GitHub
parent abc903c240
commit 622f02bf21
5 changed files with 40 additions and 5 deletions
@@ -0,0 +1,6 @@
---
"updater": patch
"updater-js": patch
---
On Windows, returns an error if failed to spawn the installer in `install` through `ShellExecuteW`
+2 -1
View File
@@ -73,7 +73,8 @@ interface Options {
/** /**
* The sound resource name or file path for the notification. * The sound resource name or file path for the notification.
* *
* Platform specific behavior: * ## Platform-specific behavior:
*
* - On macOS: use system sounds (e.g., "Ping", "Blow") or sound files in the app bundle * - On macOS: use system sounds (e.g., "Ping", "Blow") or sound files in the app bundle
* - On Linux: use XDG theme sounds (e.g., "message-new-instant") or file paths * - On Linux: use XDG theme sounds (e.g., "message-new-instant") or file paths
* - On Windows: use file paths to sound files (.wav format) * - On Windows: use file paths to sound files (.wav format)
+1
View File
@@ -69,6 +69,7 @@ import { relaunch } from '@tauri-apps/plugin-process'
const update = await check() const update = await check()
if (update) { if (update) {
await update.downloadAndInstall() await update.downloadAndInstall()
// Relaunch the app on macOS and Linux to run the newly install version
await relaunch() await relaunch()
} }
``` ```
+17 -3
View File
@@ -84,7 +84,7 @@ class Update extends Resource {
this.rawJson = metadata.rawJson this.rawJson = metadata.rawJson
} }
/** Download the updater package */ /** Download the updater package. Call {@linkcode install} later to install it */
async download( async download(
onEvent?: (progress: DownloadEvent) => void, onEvent?: (progress: DownloadEvent) => void,
options?: DownloadOptions options?: DownloadOptions
@@ -102,7 +102,14 @@ class Update extends Resource {
this.downloadedBytes = new Resource(downloadedBytesRid) this.downloadedBytes = new Resource(downloadedBytesRid)
} }
/** Install downloaded updater package */ /**
* Install downloaded updater package. Must be called after {@linkcode download}.
*
* ## Platform-specific:
*
* - **Windows:** This function exits the app after launching the updater installer successfully
* - **macOS / Linux:** You need to relaunch the app to run the newly install version
*/
async install(options?: InstallOptions): Promise<void> { async install(options?: InstallOptions): Promise<void> {
if (!this.downloadedBytes) { if (!this.downloadedBytes) {
throw new Error('Update.install called before Update.download') throw new Error('Update.install called before Update.download')
@@ -118,7 +125,14 @@ class Update extends Resource {
this.downloadedBytes = undefined this.downloadedBytes = undefined
} }
/** Downloads the updater package and installs it */ /**
* Downloads the updater package and installs it
*
* ## Platform-specific:
*
* - **Windows:** This function exits the app after launching the updater installer successfully
* - **macOS / Linux:** You need to relaunch the app to run the newly install version
*/
async downloadAndInstall( async downloadAndInstall(
onEvent?: (progress: DownloadEvent) => void, onEvent?: (progress: DownloadEvent) => void,
options?: DownloadOptions & InstallOptions options?: DownloadOptions & InstallOptions
+14 -1
View File
@@ -743,11 +743,21 @@ impl Update {
} }
/// Installs the updater package downloaded by [`Update::download`] /// Installs the updater package downloaded by [`Update::download`]
///
/// ## Platform-specific:
///
/// - **Windows:** This function exits the app after launching the updater installer successfully
/// - **macOS / Linux:** You need to relaunch the app to run the newly install version
pub fn install(&self, bytes: impl AsRef<[u8]>) -> Result<()> { pub fn install(&self, bytes: impl AsRef<[u8]>) -> Result<()> {
self.install_inner(bytes.as_ref()) self.install_inner(bytes.as_ref())
} }
/// Downloads and installs the updater package /// Downloads and installs the updater package
///
/// ## Platform-specific:
///
/// - **Windows:** This function exits the app after launching the updater installer successfully
/// - **macOS / Linux:** You need to relaunch the app to run the newly install version
pub async fn download_and_install<C: FnMut(usize, Option<u64>), D: FnOnce()>( pub async fn download_and_install<C: FnMut(usize, Option<u64>), D: FnOnce()>(
&self, &self,
on_chunk: C, on_chunk: C,
@@ -849,7 +859,7 @@ impl Update {
let file = encode_wide(file); let file = encode_wide(file);
let parameters = encode_wide(parameters); let parameters = encode_wide(parameters);
unsafe { let result = unsafe {
ShellExecuteW( ShellExecuteW(
std::ptr::null_mut(), std::ptr::null_mut(),
w!("open"), w!("open"),
@@ -859,6 +869,9 @@ impl Update {
SW_SHOW, SW_SHOW,
) )
}; };
if result as isize <= 32 {
return Err(crate::Error::Io(std::io::Error::last_os_error()));
}
std::process::exit(0); std::process::exit(0);
} }