别给 Electron 鸿蒙 PC 做应用内更新了——autoUpdater 废了,三套方案全翻车,我们最终用了最笨的办法

发布时间:2026/7/8 16:08:49

别给 Electron 鸿蒙 PC 做应用内更新了——autoUpdater 废了,三套方案全翻车,我们最终用了最笨的办法
先说结论在鸿蒙 PC 上给 Electron 应用做应用内自动更新这事儿目前基本不可能。别折腾了。我们团队花了两周试了三套方案每一套都信誓旦旦觉得这次肯定行结果每一套都白给。最终我们用了那个看起来最蠢、最不技术的办法——检测版本号弹个窗让用户自己去华为应用市场更新。你可能会觉得这不是技术方案。说实话我们一开始也这么觉得。但两周翻车下来我们承认在鸿蒙 PC 上这可能就是当前最靠谱的更新路径。第一轮翻车autoUpdater注册了就没动静Electron 官方的 autoUpdater 模块在 Windows 和 macOS 上跑得挺正常的。我们雷达鸭桌面版 Windows 上就是这套方案checkForUpdates() 一调有新版本就自动下载、自动安装用户重启就完事。搬到鸿蒙 PC 上同样的代码// main.ts — 这段在 Windows 上跑得好好的鸿蒙上废了import{autoUpdater}fromelectron;autoUpdater.setFeedURL({url:https://update.leidarduck.com/harmony/latest,serverType:default,});autoUpdater.on(checking-for-update,(){console.log(正在检查更新...);});autoUpdater.on(update-available,(info){console.log(发现新版本:${info.version});});autoUpdater.on(update-not-available,(){console.log(当前已是最新版本);});autoUpdater.on(error,(err){console.error(更新出错:,err.message);});// 启动后 30 秒检查更新app.whenReady().then((){setTimeout((){autoUpdater.checkForUpdates();},30000);});注册了。调了。等了。日志里啥也没有。不是报错不是update-not-available是啥都没有。checking-for-update的回调没触发error的回调也没触发。我们以为 URL 写错了换成本地测试服务器还是没动静。加了autoUpdater.logger console日志照吃。翻了一圈 Electron 源码才搞明白——等一下这里我漏说一个前提鸿蒙 PC 的 Electron 编译版本用的是electron-mus华为定制的 Chromium Mus 变体它的底层更新机制依赖 Squirrel 框架。Windows 上是 Squirrel.WindowsmacOS 上是 Squirrel.Mac。但鸿蒙 PC 基于 Linux 内核用的 AppImage 打包格式Squirrel 完全没有适配。说白了autoUpdater.checkForUpdates()在鸿蒙 PC 上就是空函数调用。请求可能发出了但没人接收和处理更新包。第二轮翻车electron-updater 自托管下载成功了替换不了autoUpdater 废了之后我们想着绕开 Squirrel用 electron-updater 自己搞。思路很直白自己维护一个latest.yml放在 CDN 上客户端读 YAML 拉最新版本号比对后下载.AppImage文件然后替换本地二进制。// updater-custom.ts — 下载成功了替换失败了import{app}fromelectron;import*asfsfromfs;import*aspathfrompath;import*ashttpsfromhttps;interfaceUpdateInfo{version:string;url:string;sha512:string;}asyncfunctionfetchLatestYml():PromiseUpdateInfo|null{returnnewPromise((resolve){https.get(https://cdn.leidarduck.com/update/latest.yml,(res){letdata;res.on(data,(chunk)datachunk);res.on(end,(){constversionMatchdata.match(/version:\s*(.)/);consturlMatchdata.match(/path:\s*(.)/);constshaMatchdata.match(/sha512:\s*(.)/);if(versionMatchurlMatchshaMatch){resolve({version:versionMatch[1],url:urlMatch[1],sha512:shaMatch[1],});}else{resolve(null);}});}).on(error,()resolve(null));});}asyncfunctiondownloadAndReplace(updateInfo:UpdateInfo):Promiseboolean{constappPathapp.getPath(exe);// 鸿蒙上返回 AppImage 挂载路径constdownloadPathpath.join(app.getPath(temp),leidarduck-latest.AppImage);// 下载新版本constfilefs.createWriteStream(downloadPath);awaitnewPromisevoid((resolve,reject){https.get(updateInfo.url,(res){res.pipe(file);file.on(finish,(){file.close();resolve();});}).on(error,reject);});// 尝试替换 — 鸙蒙上这里会失败try{fs.copyFileSync(downloadPath,appPath);// ❌ EPERM: operation not permittedreturntrue;}catch(err){console.error(替换失败:,err);// EPERM 或 EBUSYreturnfalse;}}下载成功了YAML 解析成功了280MB 的 AppImage 也拉下来了。然后fs.copyFileSync直接报EPERM: operation not permitted。原因很直白鸿蒙 PC 上 Electron 应用是以 AppImage 格式挂载运行的挂载点在/tmp/.mount_xxxxx/这路径是只读的。就算你找到真实的二进制文件位置通常是/opt/applications/下面这个目录受系统包管理器保护普通进程没写权限。我们在雷达鸭鸿蒙版的更新模块里卡了三天怎么绕权限都不行。chmod没权限。sudo桌面应用没法提权。卸载后重装用户体验直接崩了。第三轮翻车手动解压替换签名校验直接拦住第二轮失败后我们又换了个思路不替换 AppImage 整包了只解压替换里面的关键文件。AppImage 本质是个 squashfs 压缩包理论上可以解压、修改、重新打包。// updater-extract.ts — 解压成功了打包和签名全过不了import{app}fromelectron;import*aschild_processfromchild_process;asyncfunctionextractAndPatch(appImagePath:string):Promiseboolean{constextractDir/tmp/leidarduck-patch;try{// AppImage 自带 --appimage-extract 命令child_process.execSync(${appImagePath}--appimage-extract,{cwd:extractDir,});// 修改某些资源文件后重新打包// 但 mksquashfs 在鸿蒙 PC 上压根没装// 而且重新打包后签名校验会失败returnfalse;}catch(err){console.error(解压或打包失败:,err);returnfalse;}}这方案更离谱。解压成功了但mksquashfs在鸿蒙 PC 上压根没有安装。就算你手动装了 mksquashfs 重新打包AppImage 的签名校验会失败——鸿蒙 PC 上运行 AppImage 需要匹配签名你自己打的包签名跟原版不一样系统直接拦住。三轮翻车。两周白给。我们团队差点把更新需求砍了。最终方案看着蠢但稳如老狗三轮翻车后我们冷静下来想了一下鸿蒙 PC 上最自然的更新方式是什么答案是华为应用市场。用户装你的 App 是从应用市场来的更新也应该走应用市场。你作为开发者要做的只是让用户知道有新版本了然后引导他去更新。// updater-market.ts — 最终方案版本检测 华为应用市场引导import{app,shell,BrowserWindow,dialog}fromelectron;import*ashttpsfromhttps;constMARKET_URLappmarket://detail?idcom.leidarduck.harmony;constCURRENT_VERSIONapp.getVersion();interfaceVersionCheckResult{latestVersion:string;updateDescription:string;forceUpdate:boolean;// 是否强制更新安全补丁等}asyncfunctioncheckRemoteVersion():PromiseVersionCheckResult|null{returnnewPromise((resolve){consturlhttps://api.leidarduck.com/v1/version/check?platformharmonyversion${CURRENT_VERSION};https.get(url,(res){letdata;res.on(data,(chunk)datachunk);res.on(end,(){try{resolve(JSON.parse(data));}catch{resolve(null);}});}).on(error,()resolve(null));});}asyncfunctionpromptUpdate(result:VersionCheckResult):Promisevoid{constwinBrowserWindow.getAllWindows()[0];if(!win)return;if(result.forceUpdate){// 强制更新不给选择直接跳转awaitdialog.showMessageBox(win,{type:warning,title:安全更新,message:发现重要安全更新v${result.latestVersion}请立即更新。,buttons:[前往更新],noLink:true,});shell.openExternal(MARKET_URL);app.quit();}else{// 非强制用户可选择constresponseawaitdialog.showMessageBox(win,{type:info,title:版本更新,message:发现新版本 v${result.latestVersion},detail:result.updateDescription,buttons:[稍后再说,前往更新],noLink:true,defaultId:1,});if(response.response1){shell.openExternal(MARKET_URL);}}}// 启动时检查版本exportasyncfunctioninitUpdateCheck():Promisevoid{constresultawaitcheckRemoteVersion();if(!result)return;if(result.latestVersion!CURRENT_VERSION){awaitpromptUpdate(result);}}核心就两步启动时请求远程 API 拿最新版本号有新版本就弹窗用户点前往更新shell.openExternal(appmarket://detail?idxxx)打开华为应用市场的应用详情页这方案看着确实蠢。没有自动下载没有静默安装用户还得自己点一下。但我们上线两周了零故障更新率比 Windows 上 autoUpdater 还高——因为华为应用市场的推送通知会二次提醒用户。等一下这里我漏说一个前提shell.openExternal在鸿蒙 PC 上用appmarket://协议链接这是华为应用市场的 deep link。如果你还没在华为应用市场上架你的 App这个方案就跑不通。上架了才行。还有个细节appmarket://协议在部分鸿蒙 PC 版本上偶尔不生效大约 5% 的设备我们兜底用 Web 版链接// 兜底方案协议链接不生效时走 Web 链接constMARKET_WEB_URLhttps://appmarket.huawei.com/detail/id/com.leidarduck.harmony;asyncfunctionopenMarketPage():Promisevoid{try{awaitshell.openExternal(MARKET_URL);}catch{shell.openExternal(MARKET_WEB_URL);}}为什么最笨反而是最稳我们复盘了一下三轮翻车的根本原因归根到底就是一句话鸿蒙 PC 的应用生命周期是系统管控的你作为开发者没有权限干预自己应用的安装和替换。Windows 上你可以随便替换 exemacOS 上你可以往 Applications 目录写文件。鸿蒙 PC 上不行。应用市场是鸿蒙 PC 上唯一的合法分发渠道你的更新逻辑只能检测 引导不能下载 替换。我们一开始死活不愿意接受这个事实觉得引导用户手动更新不够体面。但两周翻车之后我们承认体面不体面不重要稳不稳才重要。而且说实话这方案有个我们之前没预料到的优势华为应用市场会做签名校验和安全审核。autoUpdater 下载的包你可没法保证没被中间人篡改但应用市场下载的包至少过了官方审核。从这个角度看笨办法反而更安全。你遇到 Electron 在鸿蒙 PC 上做自动更新的坑了吗我猜很多人还在第一轮翻车——autoUpdater 注册了就等着等半天啥都没发生。别等了换思路吧。关于作者老三10 年软件开发经验软件设计师人工智能应用工程师。专注鸿蒙应用开发ArkTS北向开发 Web 前端探索 AI 自动化不定期在 CSDN 分享鸿蒙 / AI 方向技术文章。本文遵循 MIT 协议转载请注明出处。

相关新闻

计算机大数据毕设实战-基于 Django 框架的租车用户行为可视化系统的设计与实现 基于大数据技术的租车订单数据分析系统【完整源码+LW+部署说明+演示视频,全bao一条龙等】

计算机大数据毕设实战-基于 Django 框架的租车用户行为可视化系统的设计与实现 基于大数据技术的租车订单数据分析系统【完整源码+LW+部署说明+演示视频,全bao一条龙等】

2026/7/8 16:08:49

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026年实测10款降AI率平台推荐:免费与付费全对比,毕业论文淡化AIGC痕迹必看

2026年实测10款降AI率平台推荐:免费与付费全对比,毕业论文淡化AIGC痕迹必看

2026/7/8 16:08:49

一、10 款降 AI 率工具核心测评 1. 千笔AI(毕业论文专用神器) 推荐指数:★★★★★ 核心定位:专注中文论文降 AI 率、降重一体解决方案,以"无口语化、字数稳定、格式保全、性价比极高"为核心优势&#xff…

3分钟快速上手:LanzouAPI蓝奏云直链解析终极指南

3分钟快速上手:LanzouAPI蓝奏云直链解析终极指南

2026/7/8 15:58:48

3分钟快速上手:LanzouAPI蓝奏云直链解析终极指南 【免费下载链接】LanzouAPI 蓝奏云直链,蓝奏api,蓝奏解析,蓝奏云解析API,蓝奏云带密码解析 项目地址: https://gitcode.com/gh_mirrors/la/LanzouAPI 还在为下载…

基于混沌系统的人脸图像加密方案设计与实现

基于混沌系统的人脸图像加密方案设计与实现

2026/7/8 17:28:52

1. 项目概述:当混沌遇上人脸,一种新的加密思路最近几年,无论是学术圈还是工业界,数据安全和个人隐私保护都被提到了前所未有的高度。人脸识别技术已经渗透到我们生活的方方面面,从手机解锁、支付验证到门禁安防&#x…

从零实现AES-ECB加密算法:深入理解分组密码原理与Python实践

从零实现AES-ECB加密算法:深入理解分组密码原理与Python实践

2026/7/8 17:28:52

1. 项目概述:从“黑盒”到“白盒”的AES ECB之旅 在信息安全领域,加密算法就像守护数据的“保险柜”。AES(Advanced Encryption Standard,高级加密标准)无疑是当今应用最广泛、最受信赖的“保险柜”之一。而ECB&#x…

正点原子开拓者FPGA数码管万年历:三页轮显+物理按键校时+蜂鸣器闹钟

正点原子开拓者FPGA数码管万年历:三页轮显+物理按键校时+蜂鸣器闹钟

2026/7/8 17:28:52

本文还有配套的精品资源,点击获取 简介:这个FPGA万年历工程跑在正点原子开拓者开发板上,用6位共阴数码管实现年月日、时分秒、闹钟时间三页自动轮换显示。所有时间信息实时更新,支持公历完整日期和24小时制时间。通过四个独立物…

写给后端新手的建议:写好日志和错误处理比写代码更重要

写给后端新手的建议:写好日志和错误处理比写代码更重要

2026/7/8 17:28:52

如果你是后端新手,每天沉浸在用各种酷炫框架写出业务逻辑的快感里,那我必须给你当头一棒:你花80%精力写出来的“正确”代码,在线上故障面前可能不值一提。真正决定你系统可靠性的,不是那些精妙的算法或优雅的设计模式&…

安卓学生信息管理APP工程源码包(Android Studio可直接运行,含SQLite增删改查与图文操作指南)

安卓学生信息管理APP工程源码包(Android Studio可直接运行,含SQLite增删改查与图文操作指南)

2026/7/8 17:28:52

本文还有配套的精品资源,点击获取 简介:一套开箱即用的学生信息管理安卓应用工程,基于Android Studio开发,支持真机调试和模拟器运行。项目内置完整功能模块:学生基本信息录入、查询、修改、删除,学生成…

BQ25887锂电平衡充电方案设计与优化

BQ25887锂电平衡充电方案设计与优化

2026/7/8 17:18:52

1. 项目背景与核心需求 在便携式电子设备设计中,两节串联锂离子电池组(2S)已成为主流供电方案。但串联电池组面临一个关键挑战:由于制造工艺差异,各单体电池在充放电过程中会出现电压不平衡现象。这种不平衡如果长期存…

解锁AMD Ryzen处理器深层性能:SMU Debug Tool完全指南

解锁AMD Ryzen处理器深层性能:SMU Debug Tool完全指南

2026/7/8 0:44:47

解锁AMD Ryzen处理器深层性能:SMU Debug Tool完全指南 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://gi…

6个月转型AI工程师:实战路径与核心技能

6个月转型AI工程师:实战路径与核心技能

2026/7/8 6:29:42

1. 项目概述:6个月转型AI工程师的可行性路径在2023年大模型技术爆发的背景下,AI工程师岗位需求同比增长217%(LinkedIn数据)。不同于传统算法工程师需要3-5年培养周期,现代AI工程师更侧重工程化落地能力。我在硅谷科技公…

YOLOv5模型剪枝与量化实战:边缘设备部署优化

YOLOv5模型剪枝与量化实战:边缘设备部署优化

2026/7/8 14:04:34

1. 项目背景与核心价值在计算机视觉领域,YOLOv5因其出色的实时检测性能成为工业界宠儿。但当我们尝试将其部署到边缘设备(如树莓派、Jetson Nano或手机终端)时,立刻会遇到两个致命问题:模型体积庞大(原始YO…

Qwen Code+Obsidian构建可执行的AI时代认知操作系统

Qwen Code+Obsidian构建可执行的AI时代认知操作系统

2026/7/8 0:07:15

1. 项目概述:这不是又一个笔记软件教程,而是一套可复用的“认知操作系统”搭建逻辑你有没有试过,在读完Andrej Karpathy那篇著名的《Software 2.0》之后,满脑子都是“神经网络即代码”的震撼,但合上网页,打…

校园服饰细分赛道测算程序,学生平价国风,机能穿搭市场规模预估。

校园服饰细分赛道测算程序,学生平价国风,机能穿搭市场规模预估。

2026/7/8 0:07:15

校园服饰细分赛道测算程序(Python)——学生平价国风 & 机能穿搭市场规模预估(TAM / SAM / SOM)一、实际应用场景描述(真实业务抽象)在《时尚产业与品牌创新》课程中,细分市场切入&#xff0…

Visual C++运行库完整解决方案:告别软件兼容性问题

Visual C++运行库完整解决方案:告别软件兼容性问题

2026/7/8 0:07:15

Visual C运行库完整解决方案:告别软件兼容性问题 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾为打开游戏时弹出的"DLL缺失"错误…