ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Squirrel.Windows UpdateManager 使用指南:Easy Mode 与分步式更新实战

Squirrel.Windows UpdateManager 使用指南:Easy Mode 与分步式更新实战 开发工具【免费下载链接】Squirrel.WindowsAn installation and update framework for Windows desktop apps项目地址https://gitcode.com/gh_mirrors/sq/Squirrel.Windows点击查看免费下载本文是 Squirrel.Windows 项目中 UpdateManager Reference 的深入实践版。你将掌握UpdateApp一键更新与CheckForUpdate/DownloadReleases/ApplyReleases分步控制两套更新 API 的完整用法理解UpdateInfo与ReleaseEntry的数据结构语义并看到它们如何与仓库源码src/Squirrel/下的实现与test/Squirrel.Tests/的测试一一对应从而在自己的 Windows 桌面应用中落地可靠的自更新机制。1. UpdateManager 是什么UpdateManager是 Squirrel.Windows 提供给应用开发者的核心入口类封装了检查更新 → 下载包 → 应用包 → 维护快捷方式与卸载信息的完整链路。它以partial class形式分布在多个文件中UpdateManager.cs、UpdateManager.CheckForUpdates.cs、UpdateManager.DownloadReleases.cs、UpdateManager.ApplyReleases.cs并实现IUpdateManager接口定义于 IUpdateManager.cs。构造时只需给出发布源地址其余均可选public UpdateManager(string urlOrPath, string applicationName null, string rootDirectory null, IFileDownloader urlDownloader null)urlOrPath发布源。可以是 HTTP(S) 地址如静态托管目录或 GitHub Releases也可以是本地磁盘目录用于测试或内网分发。源码通过Utility.IsHttpUrl判断走网络下载还是文件复制分支。applicationName应用名缺省时由getApplicationName()从Update.exe所在目录名推断。rootDirectory安装根目录缺省为GetLocalAppDataDirectory()推导出的本地应用数据目录最终实际目录为rootDirectory applicationName。urlDownloader可注入自定义下载器缺省为FileDownloader见 FileDownloader.cs。注意两点UpdateManager实现了IDisposable且析构函数会校验updateLock是否被释放未释放会抛出 You must dispose UpdateManager!。因此务必使用using或手动Dispose()。每次更新操作前会通过acquireUpdateLock()获取基于应用目录 SHA1 命名的全局互斥锁SingleGlobalInstance见 UpdateManager.cs防止多个实例并发执行更新拿不到锁会抛TimeoutException。2. Easy Mode一键完成全部更新UpdateApp是文档所称的 Easy Mode下载并更新应用到最新版本一次调用完成所有步骤。它是定义在 IUpdateManager.cs 中EasyModeMixin的扩展方法public static async TaskReleaseEntry UpdateApp(this IUpdateManager This, Actionint progress null)其内部执行顺序对应src/Squirrel/IUpdateManager.cs中的EasyModeMixin.UpdateAppCheckForUpdate进度占 0–33%DownloadReleases(updateInfo.ReleasesToApply)进度占 33–66%ApplyReleases(updateInfo)进度占 66–99%CreateUninstallerRegistryEntry()维护程序和功能卸载项返回最新版本对应的ReleaseEntry若没有更新则返回default(ReleaseEntry)。值得注意的重试逻辑若上述步骤抛出异常且当前未忽略 delta 更新代码会把ignoreDeltaUpdates置为true并goto retry重跑一遍——即delta 包失败自动回退到全量包这与CheckForUpdate的ignoreDeltaUpdates参数设计一致。典型用法来自文档描述与 API 设计using (var mgr new UpdateManager(https://example.com/updates/)) { var updatedRelease await mgr.UpdateApp(progress { Console.WriteLine($更新进度: {progress}%); }); }如果应用基于 .NET Core需要创建快捷方式时注意CreateShortcutForThisExe会把入口.dll替换为同名的.exe见 IUpdateManager.cs因为对.dll创建快捷方式无效。3. Advanced Mode分步控制更新流程当需要更细粒度控制例如在 UI 上分阶段展示进度、先下载后择机应用、或把下载与应用拆到不同时机时使用以下三个方法。三者均为Task异步方法接口签名定义在 IUpdateManager.csTaskUpdateInfo CheckForUpdate( bool ignoreDeltaUpdates false, Actionint progress null, UpdaterIntention intention UpdaterIntention.Update); Task DownloadReleases( IEnumerableReleaseEntry releasesToDownload, Actionint progress null); Taskstring ApplyReleases( UpdateInfo updateInfo, Actionint progress null);3.1 CheckForUpdate查询是否存在可用更新作用从服务器拉取RELEASES清单与本地RELEASES对比返回封装了待更新信息的UpdateInfo。实现要点UpdateManager.CheckForUpdates.cs网络模式下先下载远端RELEASES最多重试 3 次若本地已有版本还会附加id、localVersion、archamd64/x86查询参数便于服务端做定制响应。本地目录模式下若目录中没有RELEASES文件但存在*.nupkg会自动扫描包并生成一份。下载/读取完成后调用ReleaseEntry.ParseReleaseFileAndApplyStaging(releaseFile, stagingId)解析并应用分批发布staged rollout过滤——stagingId是存放在packages\.betaId文件中的用户 GUID据此决定该用户是否命中某版本的发布比例见 ReleaseEntry.cs 的IsStagingMatch。参数ignoreDeltaUpdates为true时忽略所有 delta 包、直接取最新全量包intention为Install时按全新安装处理本地无版本可比、并生成 staging ID 逻辑不同。3.2 DownloadReleases下载发布包到本地作用把UpdateInfo.ReleasesToApply指定的nupkg含 delta 增量包从服务器下载到本地packages目录。实现要点UpdateManager.DownloadReleases.cs网络模式用urlDownloader.DownloadFile逐包下载并汇报进度本地目录模式则直接File.Copy。下载完成后对每个包执行checksumPackage校验文件大小与 SHA1来自RELEASES清单不匹配即删除文件并抛异常从源头杜绝损坏包进入安装流程。3.3 ApplyReleases应用已下载的发布包作用安装已下载的包返回新版本对应的app-[version]目录完整路径。实现要点UpdateManager.ApplyReleases.cs若ReleasesToApply中含 delta 包先通过createFullPackagesFromDeltas将上一全量包 delta合成完整nupkg进度 0–40%若列表为空无更新且是安装场景则直接运行应用并返回当前版本目录。解压到app-version目录进度 40–80%解压期间写入.not-finished标记文件防止半途中断留下假成功目录随后重建本地RELEASES、自更新Update.exe、触发 Squirrel 事件钩子、清理失效的固定任务栏快捷方式、删除过期版本目录。返回值ret即新版本的app-version完整路径可据此定位新版本程序入口。3.4 组合示例分步更新的完整代码using (var mgr new UpdateManager(https://example.com/updates/, MyApp)) { // 1. 检查更新 var updateInfo await mgr.CheckForUpdate(progress Console.WriteLine($检查: {progress}%)); if (updateInfo.ReleasesToApply.Any()) { // 2. 下载发布包 await mgr.DownloadReleases(updateInfo.ReleasesToApply, progress Console.WriteLine($下载: {progress}%)); // 3. 应用更新得到新版本目录 var newVersionDir await mgr.ApplyReleases(updateInfo, progress Console.WriteLine($应用: {progress}%)); Console.WriteLine($已更新到: {newVersionDir}); } else { Console.WriteLine(已是最新版本); } }注意UpdateInfo必须来自CheckForUpdate的返回值——ApplyReleases内部会读取updateInfo.PackageDirectory与ReleasesToApply跨实例拼装会导致路径错误。4. UpdateInfo更新信息载体UpdateInfo是CheckForUpdate的返回类型也是DownloadReleases/ApplyReleases的输入。类定义于 UpdateInfo.cs三个核心属性与文档中的描述一致public class UpdateInfo { public ReleaseEntry CurrentlyInstalledVersion; // 当前已安装版本 public ReleaseEntry FutureReleaseEntry; // 将要安装到的目标版本 public ListReleaseEntry ReleasesToApply; // 需要下载/应用的发布列表 }从源码可以补充几个重要语义构造逻辑UpdateInfo.csFutureReleaseEntry取ReleasesToApply中版本号最大者若列表为空无更新则等于CurrentlyInstalledVersion。首次安装bootstrap时CurrentlyInstalledVersion为null。IsBootstrapping当CurrentlyInstalledVersion null时为true表示处于首次安装而非升级UpdateInfo.cs。Create静态工厂UpdateInfo.cs是版本决策的核心要求远端必须存在至少一个全量包否则抛 There should always be at least one full release本地版本已不低于远端最新全量包时ReleasesToApply为空无更新否则收集所有高于本地版本的发布比较所有 delta 包总大小与最新全量包大小取体积更小者——这正是文档所述计算哪个下载总量更少的实现本地无版本时直接返回最新全量包。FetchReleaseNotes从每个待应用包的 nuspec 中读取ReleaseNotes可用于在更新 UI 中展示变更日志UpdateInfo.cs。对应测试见 UpdateManagerTests.csWhenTwoRemoteUpdatesAreAvailableChoosesDeltaVersion验证了 delta 优先策略且ignoreDeltaUpdates: true时回退到全量包。5. ReleaseEntry单个发布的描述ReleaseEntry描述一个具体发布文件接口定义于 ReleaseEntry.cspublic interface IReleaseEntry { string SHA1; // 包文件 SHA1 校验值40 位十六进制 string Filename; // 包文件名可含 HTTP 基址解析时拆分 long Filesize; // 文件字节数 bool IsDelta; // 是否为 delta 增量包文件名以 -delta.nupkg 结尾 string EntryAsString; // 在 RELEASES 文件中的序列化行 SemanticVersion Version; // 从文件名解析出的语义版本 string PackageName; // 包名 float? StagingPercentage; // 分批发布比例如 0.1 10% string GetReleaseNotes(string packageDirectory); Uri GetIconUrl(string packageDirectory); }ReleaseEntry与文档中给出的字段一一对应且SHA1、Filename、Filesize、IsDelta均带[DataMember]特性支持序列化传输。文档中的ReleaseEntry以接口形式列出四个成员在实现类中还有几个高频使用的扩展能力EntryAsString把条目格式化为RELEASES文件行。带分批发布比例时形如SHA1 BaseUrl文件名 大小 # 10%否则为SHA1 文件名 大小ReleaseEntry.cs。ParseReleaseEntry按正则解析一行清单支持#注释、URL 形式文件名自动拆分出BaseUrl与Query并校验 SHA1 必须为 40 位、文件名不能含非法路径字符ReleaseEntry.cs。Version/PackageName分别从文件名解析语义版本与包名ReleaseEntry.cs。一个完整的RELEASES文件由多行EntryAsString构成按版本升序、全量包在前排序可由WriteReleaseFile生成ReleaseEntry.cs。仓库测试夹具目录test/Squirrel.Tests/fixtures/下的RELEASES-OnePointOh与RELEASES-OnePointOne是真实的清单样例可用于核对格式。6. 与 Update Process 全流程的对应关系仓库文档 update-process.md 描述了UpdateManager每次运行时的完整步骤可与上文三个方法一一对应检查更新下载/读取远端RELEASES并与本地对比 →CheckForUpdate对应 UpdateManager.CheckForUpdates.cs。下载并校验包按delta 总大小 vs 全量包大小择优下载并用清单中的 SHA1/大小校验 →DownloadReleases与checksumPackage对应 UpdateManager.DownloadReleases.cs。由 delta 合成全量包createFullPackagesFromDeltas逐级应用增量对应 UpdateManager.ApplyReleases.cs。安装新版本解压到app-version目录如%LocalAppData%\MyApp\app-1.0.1对应installPackageToAppDir。更新快捷方式桌面与开始菜单快捷方式通过传给Update.exe的--processStart参数指向新版本固定到任务栏的快捷方式由fixPinnedExecutables重定向对应 UpdateManager.ApplyReleases.cs。旧版本清理下次启动时删除除当前版本与紧邻上一版本之外的所有app-*目录cleanDeadVersions对应 UpdateManager.ApplyReleases.cs并为无法删除的目录写入.dead标记避免重复触发卸载钩子。同时注意当前版本没有内置回滚rollback支持——这是文档 update-process.md 明确说明的现状设计上需要自行保留上一版本目录或依赖全量包降级。7. 更多辅助能力除三个核心方法外IUpdateManagerIUpdateManager.cs还提供安装/卸载配套 APIFullInstall/FullUninstall完整安装 / 卸载实现于 UpdateManager.cs。FullInstall内部串联CheckForUpdate以Install意图→DownloadReleases→ApplyReleases。CreateUninstallerRegistryEntry/RemoveUninstallerRegistryEntry在程序和功能中创建/移除卸载项默认调用update.exe --uninstall。CreateShortcutsForExecutable/RemoveShortcutsForExecutable/GetShortcutsForExecutable按ShortcutLocation枚举StartMenu、Desktop、Startup、AppRoot管理快捷方式支持programArguments与自定义图标。CurrentlyInstalledVersion从可执行文件路径解析出app-version目录对应的语义版本若不在应用目录内则返回null。RestartApp/RestartAppWhenExited把 EXE 名与参数交给Update.exe的--processStartAndWait待当前进程退出后由它拉起新版本UpdateManager.cs。若使用 GitHub 托管发布可直接用GitHubUpdateManager(repoUrl, ...)工厂方法UpdateManager.Factory.cs它会调用 GitHub Releases API 找到最新发布支持prerelease与私有仓库accessToken参数再把下载地址交给标准UpdateManager。该流程的说明见 github.md。8. 调试与验证建议仓库自带一套完整的测试可用于验证上述行为是否符合预期UpdateManagerTests.csInitialInstallSmokeTest验证FullInstall后packages\RELEASES生成、app-1.0.0.0目录内容正确。WhenBothFilesAreInSyncNoUpdatesAreApplied/WhenRemoteReleasesDoNotHaveDeltasNoUpdatesAreApplied验证无更新时ReleasesToApply为空。WhenTwoRemoteUpdatesAreAvailableChoosesDeltaVersion验证 delta 优先、ignoreDeltaUpdates回退全量。WhenReleasesFileDoesntExistThrowACustomError/WhenReleasesFileIsBlankThrowAnException验证异常路径。CurrentlyInstalledVersionTests验证版本解析逻辑含非应用目录返回null的场景。实际接入时把UpdateManager的urlOrPath指向一个静态文件服务器或本地目录即可完成端到端演练借助 debugging-updates.md 可进一步排查更新目录问题。需要注意UpdateManager依赖Update.exe存在getUpdateExe找不到时会抛 Update.exe not found, not a Squirrel-installed app?因此调试环境应尽量贴近真实安装布局如 getting-started 中描述的安装流程。赞分享开发工具【免费下载链接】Squirrel.WindowsAn installation and update framework for Windows desktop apps项目地址https://gitcode.com/gh_mirrors/sq/Squirrel.Windows点击查看免费下载相关推荐Squirrel.Windows 应用更新实战从 Releasify 产物到 UpdateManager 的完整升级链路Squirrel.Windows 应用更新实战从 Releasify 产物到 UpdateManager 的完整升级链路 本文基于 Squirrel.Wind开发工具Squirrel.Windows 集成指南在 Windows 桌面应用中接入 UpdateManager 实现自动更新Squirrel.Windows 集成指南在 Windows 桌面应用中接入 UpdateManager 实现自动更新 本文是 Squirrel.Window开发工具Frame部署完全指南从本地开发到生产环境的完整流程Frame部署完全指南从本地开发到生产环境的完整流程 Frame是一个功能强大的用户系统API启动器能够帮助开发者快速构建安全可靠的用户认证与管理系统。本指后端上一篇Navicat密码解密3种方法帮你找回丢失的数据库连接凭证下一篇如何5分钟完成Ghidra逆向工程工具的终极安装指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表