首页 / 资讯中心 / 文章详情

自己替换自己有多难?ArtCraft Launcher跨平台自更新机制源码剖析

自己替换自己有多难?ArtCraft Launcher跨平台自更新机制源码剖析 ★ FEATURED ARTICLE
【免费下载链接】craft-launcherThe Craft App Launcher项目地址https://gitcode.com/gh_mirrors/cr/craft-launcher点击查看免费下载ArtCraft Launcher 是一个纯 Rust 编写的跨平台应用启动器负责安装、更新和启动整个 Craft App Suite。它还有一个隐藏技能自己能更新自己。一个正在运行的程序如何安全地下载、校验并替换掉自己的可执行文件这篇文章带你完整剖析它的跨平台自更新机制。为什么自己替换自己这么难 自更新要同时跨过三道坎文件锁Windows 会锁住正在运行的.exe你根本没法在运行时直接覆盖它单实例锁ArtCraft Launcher 同一时间只允许一个实例新版本启动时旧版本还占着位置会互相顶掉多形态安装macOS 是.app打包目录Windows 有 MSI 和绿色 zip 两种Linux 有 AppImage、.deb、.rpm三种。每种装进来的方式都必须用同一种方式换出去否则安装会漂移。源码作者在 crates/native/src/self_update.rs 开头用一张表把答案讲得很直白安装形态替换方式macOS.app直接从 DMG 把新包覆盖到.app运行时可写然后重新打开Windows MSI退出后由助手进程静默运行新 MSI重装回原目录再启动 exeWindows 绿色 zip退出后把新 zip 解包覆盖到当前目录设置文件不受影响Linux AppImage把新 AppImage 重命名覆盖旧的运行时可行再启动Linux.deb/.rpm交给系统包管理器会弹密码框然后重启其余情况Flatpak、FreeBSD、开发构建则放弃自更新只给下载链接。第一步先搞清楚我是怎么被装上的 自更新的第一步是自我认知。Install枚举self_update.rs#L37-L48列出了五种可自更新的形态current()会调用detect()判断当前进程属于哪一种macOS向上找.app目录读Info.plist里的CFBundleIdentifier确认是自家 bundleWindowsexe 旁边有portable.txt就是绿色版否则查注册表HKCU\Software\Learning Machines LLC\ArtCraft Launcher的InstallDir或默认安装目录匹配上才算 MSI 安装Linux读APPIMAGE环境变量判断 AppImage在沙箱Flatpak里直接返回None/usr/bin下的二进制则用dpkg-query和rpm -q确认包管理器。这个判断的结果会写进 UI 能力位 Capabilities::self_update——能力为false时界面上的按钮会从更新并重启降级为下载优雅兜底。第二步下载新安装包先验明正身 更新走的是和普通 Craft 应用完全相同的下载通道。pick_asset()会根据当前安装形态挑对应文件MSI 安装就挑.msiAppImage 就挑.AppImage再由 download() 完成下载规则很严格文件名必须合法防路径穿越必须有 SHA-256 校验值优先用 Release 里的 digest没有就抓 SHA256SUMS.txt 补上发布方没提供校验和的文件直接拒绝安装——没有凭证背书的东西绝不落地。Release 结构 对 GitHub 返回的一切视为不可信输入下载链接必须指向仓库自己的 release 下载地址否则整条 asset 被丢弃。第三步等老进程退出助手进程接力 ⏳这是整套机制最精妙的部分核心思想只有一句老进程负责换文件新进程由一个看守者负责启动。下载并校验完成后先写入一个 self-update 标记self-update.txt记录 tag 和时间戳防止更新完重启后又被提示更新同一版本造成死循环通过 claim_restart() 等待其他正在安装的应用全部结束最多等 10 分钟可手动取消避免重启把别人的安装腰斩启动一个脱离父进程的助手Unix 上是一段sh脚本helper_command每 0.1 秒轮询kill -0 $pid等老进程退出Windows 上是一个隐藏窗口的 PowerShellwindows_helper先Wait-Process再跑 MSI 或解包脚本最后Start-Process启动新 exe老进程退出助手把新版本拉起来。那新实例启动时万一旧实例还没完全死透怎么办single_instance.rs 里有个版本握手机制后启动的实例会向监听端口发hello 版本运行中的实例回答running 版本——后来者版本更新就先退位让路。所以哪怕新旧版本短暂共存结果也一定是新版接管、旧版退出。几个平台细节很能体现功力AppImage 替换replace_appimage先拷一份临时文件到旁边rename原子覆盖。运行中的副本挂载自已断链的 inode所以覆盖不影响自己运行Windows MSI用/passive /norestart静默重装到同一目录MSI 向导记录的安装目录用户级安装无需管理员macOS.app直接从下载的 DMG 把新 bundle 拷过去——.app是目录运行时可写连重启都能省一步等待。用户看到的是什么✨对普通用户来说整个流程只有两个入口检测到新版本后窗口顶部出现一条横幅ArtCraft Launcher v0.2.0 可用按钮是更新并重启每个新版本只弹窗询问一次launcher_update_dialog更新进行中横幅变成进度条依次显示Downloading…→Verifying…→Waiting for other installs…→Installing, then restarting…views.rs#L150-L172如果开启了自动更新trigger_auto_updates() 会在后台自动排队执行每个版本只尝试一次。检查更新本身也把自己算进去了backend 在后台线程把整套 Craft 应用加上自己一起查最新版本发现新版且 24 小时内没更新过时才发出LauncherUpdate事件backend.rs#L256-L266。小结ArtCraft Launcher 的自更新设计可以总结为四个原则同进同出——用什么形态装的就用什么形态换先验后装——没有 SHA-256 背书的新包一律拒绝助手接力——老进程只负责善后启动新版的脏活交给脱离的助手进程优雅兜底——能力判断不过就降级为请下载绝不硬来。想继续深挖推荐从 self_update.rs 开始读起它的文件头注释本身就是一份优秀的跨平台自更新设计文档。赞分享【免费下载链接】craft-launcherThe Craft App Launcher项目地址https://gitcode.com/gh_mirrors/cr/craft-launcher点击查看免费下载相关推荐EnvironmentalBERT-biodiversity社区贡献指南如何参与开源环境AI项目EnvironmentalBERT biodiversity社区贡献指南如何参与开源环境AI项目 EnvironmentalBERT biodiversity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站