Electron Updater在macOS下载更新后无法安装(Squirrel.Mac)
Electron-updater macOS端quitAndInstall()无响应,更新循环问题
环境信息
- macOS版本:Ventura 13.1 / Monterey
- Electron版本:21.3.0
- Electron-builder版本:23.6.0
- Electron-updater版本:5.3.0
- Node版本:19.0.1
问题现象
跨平台Electron应用部署在Github,Windows端自动更新正常,macOS端存在以下问题:
- 应用启动正常,能检测到更新并完成下载,触发
update-downloaded事件 - 用户点击「安装并重启」后,调用
quitAndInstall()无任何反应,应用既不退出也不重启 - 手动重启应用后,会再次触发更新提示,陷入循环;更新包已下载到本地但旧版本未被替换
相关代码
autoUpdater.checkForUpdatesAndNotify(); autoUpdater.on('update-downloaded', (info) => { // Show a dialog asking the user if they want to restart the app to install the update dialog.showMessageBox({ type: 'question', buttons: ['Install and Restart', 'Later'], defaultId: 0, message: 'A new update has been downloaded. Would you like to install and restart the app now?' }, (response) => { if (response === 0) { // User clicked 'Install and Restart' autoUpdater.quitAndInstall(); } }); });
更新日志(关键片段)
[2023-01-08 11:37:05.284] [info] Checking for update [2023-01-08 11:37:06.789] [info] Found version 1.0.8 (url: Duolance-Tracker-1.0.8-mac.zip, Duolance-Tracker-1.0.8.dmg) [2023-01-08 11:37:06.791] [info] Downloading update from Duolance-Tracker-1.0.8-mac.zip, Duolance-Tracker-1.0.8.dmg [2023-01-08 11:37:06.796] [warn] sysctl shell command to check for macOS Rosetta environment failed: Error: Command failed: sysctl sysctl.proc_translated sysctl: unknown oid 'sysctl.proc_translated' [2023-01-08 11:37:06.800] [info] Checked 'uname -a': arm64=false [2023-01-08 11:37:07.162] [info] Update has already been downloaded to /Users/ardaakcabuyuk/Library/Application Support/Caches/duolancetracker-updater/pending/Duolance-Tracker-1.0.8-mac.zip). [2023-01-08 11:37:10.983] [info] / requested [2023-01-08 11:37:10.988] [info] /3cd1718f82c50e8105236129abe5fcfac9263b740235c99b2b23bc22cfd581c9d49d1e30dbbb897397f626e45c20d0fda5dc02336633b6cabf7214322e322714.zip requested [2023-01-08 11:37:10.989] [info] /3cd1718f82c50e8105236129abe5fcfac9263b740235c99b2b23bc22cfd581c9d49d1e30dbbb897397f626e45c20d0fda5dc02336633b6cabf7214322e322714.zip requested by Squirrel.Mac, pipe /Users/ardaakcabuyuk/Library/Application Support/Caches/duolancetracker-updater/pending/Duolance-Tracker-1.0.8-mac.zip
构建配置(mac部分)
"mac": { "asarUnpack": "**/*.node", "category": "public.app-category.productivity", "target": [ "default" ], "icon": "build/icon.icns", "entitlements": "build/sign/entitlements.mac.plist", "entitlementsInherit": "build/sign/entitlements.mac.plist", "hardenedRuntime": true, "gatekeeperAssess": false, "extendInfo": { "NSAppTransportSecurity": { "NSAllowsArbitraryLoads": true }, "NSExceptionDomains": { "localhost": { "NSTemporaryExceptionAllowsInsecureHTTPSLoads": false, "NSIncludesSubdomains": false, "NSTemporaryExceptionAllowsInsecureHTTPLoads": true, "NSTemporaryExceptionMinimumTLSVersion": "1.0", "NSTemporaryExceptionRequiresForwardSecrecy": false } } } }
已排查内容
- 完成应用签名与公证,确认问题与此无关
- 排除系统版本影响,Ventura 13.1和Monterey均出现相同问题
解决方案建议
- 确保窗口完全关闭后再调用quitAndInstall
macOS下如果有未关闭的窗口,可能会阻塞quitAndInstall的执行,修改代码如下:
autoUpdater.on('update-downloaded', (info) => { dialog.showMessageBox({ type: 'question', buttons: ['Install and Restart', 'Later'], defaultId: 0, message: 'A new update has been downloaded. Would you like to install and restart the app now?' }, (response) => { if (response === 0) { // 关闭所有窗口 BrowserWindow.getAllWindows().forEach(win => win.close()); // 延迟执行,确保窗口关闭完成 setTimeout(() => { autoUpdater.quitAndInstall(false, true); }, 1000); } }); });
注意:quitAndInstall的第二个参数设为true,强制重启应用。
- 检查应用权限与安装路径
- 确保应用安装在
/Applications目录下,而非用户目录的受限位置(比如Downloads),避免写入权限不足 - 检查entitlements文件,确保包含必要的文件操作权限,比如添加:
<key>com.apple.security.files.user-selected.read-write</key> <true/>
- 调整electron-updater配置
- 初始化时设置
autoUpdater.allowDowngrade = false,避免版本判断逻辑出错 - 确认Github发布的asset是正确的mac构建产物(zip包而非dmg,因为electron-updater默认优先使用zip进行更新)
- 降级/升级依赖版本
- 尝试将electron-updater降级到
5.2.1,该版本修复过部分macOS更新问题 - 检查Electron与electron-builder的兼容性,Electron 21对应的electron-builder 23.x是否存在已知bug,可尝试升级到electron-builder 24.x(需确认版本兼容)
- 手动触发更新逻辑(极端方案)
如果上述方法无效,可尝试手动调用系统命令重启应用:
const { exec } = require('child_process'); const app = require('electron').app; // 在用户确认更新后执行 exec(`open "${app.getPath('applications')}/Duolance Tracker.app"`, (err) => { if (!err) { app.quit(); } });
内容的提问来源于stack exchange,提问作者Arda Akça Büyük
相关产品推荐
相关产品推荐

