尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Squirrel.Windows 自定义 Squirrel 事件完整指南:让应用响应安装、更新与卸载生命周期

发布时间:2026/9/26 9:51:54

资讯中心
01
ARTICLE

Squirrel.Windows 自定义 Squirrel 事件完整指南:让应用响应安装、更新与卸载生命周期

Squirrel.Windows 自定义 Squirrel 事件完整指南:让应用响应安装、更新与卸载生命周期
开发工具【免费下载链接】Squirrel.WindowsAn installation and update framework for Windows desktop apps项目地址https://gitcode.com/gh_mirrors/sq/Squirrel.Windows点击查看免费下载Squirrel.Windows 的安装与更新框架在安装时默认不会执行任何业务代码——它只是把 NuGet 包内容解压到本地应用目录。本指南围绕 docs/using/custom-squirrel-events.md 展开讲解如何通过标记Squirrel-Aware让安装在应用内的 EXE 在安装、更新、卸载等关键节点被调用从而创建快捷方式、注册卸载项、弹出欢迎界面等。读完本文你将掌握 C# 与原生非 C#应用的两种 Squirrel-Aware 标记方式、SquirrelAwareApp.HandleEvents的正确用法、五个事件命令行参数的语义以及底层调度机制的源码级实现。为什么需要自定义 Squirrel 事件Squirrel 的设计哲学是框架本身在安装时几乎不做任何事情。它只负责把包解压、把Update.exe放到应用目录然后调用你的应用去完成剩余的工作。文档原文明确指出Squirrel doesnt do much of anything at installation time automaticallySquirrel 在安装时不会自动做太多事情。这与传统installer DLL方案形成鲜明对比由于 Squirrel 的事件回调代码是运行在你自己应用进程内的你可以直接使用自己项目的全部代码、类库和配置来完成安装/更新逻辑而不是在一个受限的独立安装器进程里重新实现一遍。例如在onInitialInstall回调中你可以直接调用mgr.CreateShortcutForThisExe()创建快捷方式也可以顺便注册文件关联、写入自己的配置文件。默认行为Squirrel-Aware 之前的自动快捷方式当你的包中没有任何EXE 被标记为 Squirrel-Aware 时Squirrel 会替你做一件事为应用包中的每一个 EXE自动在桌面Desktop和开始菜单Start Menu各创建一个快捷方式。但一旦你为哪怕一个 EXE 启用了 Squirrel 事件这个自动行为就会关闭——快捷方式的创建责任完全转移到你的代码里。这是最容易被忽略的坑标记 Squirrel-Aware 后如果不写创建快捷方式的回调用户安装完会发现桌面和开始菜单里什么都没有。从源码看这个自动行为实现在 src/Squirrel/UpdateManager.ApplyReleases.cs 的invokePostInstall方法中当检测到的 Squirrel-Aware 应用数量为 0 时框架会遍历版本目录下所有非squirrel.前缀的 EXE并为它们调用CreateShortcutsForExecutable(..., ShortcutLocation.Desktop | ShortcutLocation.StartMenu, ...)。第一步让应用变得 Squirrel Aware要让 Squirrel 在安装/更新/卸载时调用你的 EXE必须先在 EXE 的元数据里声明SquirrelAwareVersion 1。Squirrel 通过 src/Squirrel/SquirrelAwareExecutableDetector.cs 中的GetPESquirrelAwareVersion检测该值检测顺序为先查 .NET 程序集的自定义属性查不到再查 PE 版本资源块Version Block。C# 应用通过AssemblyInfo.cs声明在你的AssemblyInfo.cs中添加一行[assembly: AssemblyMetadata(SquirrelAwareVersion, 1)]这是 C#.NET Framework / .NET Core / .NET 5应用最直接的方式。底层检测逻辑在SquirrelAwareExecutableDetector.GetAssemblySquirrelAwareVersionsrc/Squirrel/SquirrelAwareExecutableDetector.cs它用 Mono.Cecil 读取程序集自定义属性找到System.Reflection.AssemblyMetadataAttribute且键名为SquirrelAwareVersion的属性再把值解析为整数解析失败则视为未标记。非 C# 应用通过 Version Block 声明对于 C、Rust、Go 等非托管应用需要把SquirrelAwareVersion写进 PE 的英文版本信息块English Version Block通常通过App.rc资源文件完成。典型的条目如下BLOCK StringFileInfo BEGIN BLOCK 040904b0 BEGIN VALUE FileDescription, Installer for Squirrel-based applications VALUE FileVersion, 0.5.0.0 VALUE InternalName, Setup.exe VALUE LegalCopyright, Copyright (C) 2014 VALUE OriginalFilename, Setup.exe VALUE ProductName, Squirrel-based application VALUE ProductVersion, 0.5.0.0 VALUE SquirrelAwareVersion, 1 END END底层检测逻辑在GetVersionBlockSquirrelAwareValuesrc/Squirrel/SquirrelAwareExecutableDetector.cs通过GetFileVersionInfoSize/GetFileVersionInfo/VerQueryValue查询版本资源只认两种语言代码040904B0英语-美国和000004B0语言中性源码中以常量englishUS 040904B0、neutral 000004B0硬编码只要在版本块中找到SquirrelAwareVersion名称就直接返回1——源码注释里作者坦诚说明由于 Atom.exe 存在版本号解析异常这里选择只要找到名字就算 Squirrel-Aware的保守策略。注意Windows 商店风格的 MSIX 打包或改名为 .appx 的 EXE 不会被此路径检测到检测基于经典 PE 文件。第二步用SquirrelAwareApp帮助类处理事件C# 推荐对于 C# 应用文档强烈推荐使用SquirrelAwareApp帮助类src/Squirrel/SquirrelAwareApp.cs来实现事件处理。这是一个静态类核心方法HandleEvents接收五个可选回调参数触发时机回调签名回调返回后应用是否退出onInitialInstall初始安装完成ActionVersion退出exit 0onAppUpdate应用更新到新版本ActionVersion退出exit 0onAppObsoleted应用不再是新版本用户装了更新的版本ActionVersion退出exit 0onAppUninstall通过程序和功能卸载ActionVersion退出exit 0onFirstRun安装后首次正常运行Action不退出正常进入主流程文档给出的标准实现该实现复刻了默认的非 Squirrel-Aware 行为static bool ShowTheWelcomeWizard; ... static int Main(string[] args) { // NB: Note here that HandleEvents is being called as early in startup // as possible in the app. This is very important! Do _not_ call this // method as part of your apps check for updates code. using (var mgr new UpdateManager(updateUrl)) { // Note, in most of these scenarios, the app exits after this method // completes! SquirrelAwareApp.HandleEvents( onInitialInstall: v mgr.CreateShortcutForThisExe(), onAppUpdate: v mgr.CreateShortcutForThisExe(), onAppUninstall: v mgr.RemoveShortcutForThisExe(), onFirstRun: () ShowTheWelcomeWizard true); } }要点一必须在启动最早期调用。文档用醒目注释提醒不要把HandleEvents放在检查更新的代码路径里。原因在于安装/更新/卸载这些事件是通过命令行参数注入的——如果应用先走完自身的启动逻辑加载配置、连接服务、弹窗再处理事件会造成启动缓慢、与正常业务流程耦合、甚至错过退出时机。要点二大多数事件回调结束后应用必须退出。源码中HandleEvents在分发完事件后调用Environment.Exit(0)src/Squirrel/SquirrelAwareApp.cs因为 Squirrel 安装流程需要你的进程尽快让出控制权、继续后续步骤回调抛出异常则记录错误日志并Environment.Exit(-1)。唯一例外是onFirstRun——它直接return应用继续正常启动。要点三HandleEvents的arguments参数默认取Environment.GetCommandLineArgs()仅在做单元测试时通过该参数 mock 命令行生产代码保持null即可src/Squirrel/SquirrelAwareApp.cs。第三步非 C#直接处理启动命令行参数非 C# 应用无法使用SquirrelAwareApp必须在main()/入口函数里自行解析命令行。Squirrel 会以如下特殊参数启动你的 EXE文档要求你正确区分并处理参数语义处理建议--squirrel-install x.y.z.m应用被安装时调用完成应用设置如创建快捷方式、注册表项后尽快退出--squirrel-firstrun所有安装步骤完成之后调用当作一次正常启动处理可展示欢迎界面正常继续运行--squirrel-updated x.y.z.m应用更新到指定版本时调用完成后尽快退出--squirrel-obsolete x.y.z.m你的旧版本不再是新版本时调用清理旧版本残留后尽快退出--squirrel-uninstall x.y.z.m应用被卸载时调用清理自己创建的东西快捷方式、注册表项后尽快退出其中x.y.z.m是四段式版本号。调用方是Update.exe安装/更新时卸载时同样由Update.exe --uninstall触发。事件调度与参数注入的源码证据这些参数并非约定俗成而是由 src/Squirrel/UpdateManager.ApplyReleases.cs 的invokePostInstall方法真实构造并注入的安装时构造--squirrel-install {currentVersion}更新时构造--squirrel-updated {currentVersion}第 413-415 行对目录中所有 Squirrel-Aware 的 EXE逐一顺序执行并发度 1每个进程带15 秒超时cts.CancelAfter(15 * 1000)某个 hook 失败只记录日志、不中断安装第 422-432 行若是初始安装且非静默安装最后会对每个 Squirrel-Aware EXE 以--squirrel-firstrun参数Process.Start启动且不等待第 450-455 行旧版本被淘汰时会以--squirrel-obsolete {version}调用对应版本目录下的应用src/Squirrel/UpdateManager.ApplyReleases.cs卸载流程会以--squirrel-uninstall {version}调用src/Squirrel/UpdateManager.ApplyReleases.cs。从源码结构可以推断每个事件参数后面跟的版本号是 Squirrel 当前正在处理的版本目录app-x.y.z.m对应的语义版本。C# 侧SquirrelAwareApp.HandleEvents收到的Version即解析后的该值。App Setup Helper Methods事件回调里的实用工具以下方法帮助你在 Squirrel 事件回调中完成应用设置。文档特别说明如果没在使用自定义 Squirrel 事件通常不需要调用这些方法因为框架会自动处理快捷方式。快捷方式CreateShortcutsForExecutable/RemoveShortcutsForExecutableCreateShortcutsForExecutable(string exeName, ShortcutLocation locations, bool updateOnly, string programArguments, string icon)在桌面或开始菜单为指定 EXE 创建快捷方式。定义于 src/Squirrel/IUpdateManager.cs实现于 src/Squirrel/UpdateManager.ApplyReleases.cs。RemoveShortcutsForExecutable(string exeName, ShortcutLocation locations)删除对应快捷方式src/Squirrel/UpdateManager.ApplyReleases.cs。ShortcutLocation是带[Flags]的枚举src/Squirrel/IUpdateManager.cs可组合使用[Flags] public enum ShortcutLocation { StartMenu 1 0, // 开始菜单 Desktop 1 1, // 桌面 Startup 1 2, // 启动文件夹开机自启 AppRoot 1 3 // 应用目录内适合便携应用 }实现细节值得注意更新模式下不重建用户主动删除的快捷方式。源码判断if (!fileExists updateOnly)就跳过——如果用户已手动删除快捷方式Squirrel 认为这是用户意愿更新时不会骚扰用户重新创建第 233-236 行快捷方式附带AppUserModelIDcom.squirrel.{packageId}.{exeName}和由该 ID 哈希生成的 Toast Activator CLSID第 257-261 行保证开始菜单磁贴分组与通知激活正确programArguments参数会以-a ...形式追加到快捷方式命令行创建/删除后会调用fixPinnedExecutables同步修复任务栏已固定快捷方式的目标路径指向新版本目录。对于最常见的为当前正在运行的 EXE 创建/删除快捷方式框架在 src/Squirrel/IUpdateManager.cs 提供了扩展方法CreateShortcutForThisExe()/RemoveShortcutForThisExe()它们内部自动定位入口程序集并对 .NET Core 场景做了 DLL→EXE 的路径修正。这正是文档示例里mgr.CreateShortcutForThisExe()的实际调用。卸载注册表项CreateUninstallerRegistryEntry/RemoveUninstallerRegistryEntryCreateUninstallerRegistryEntry()基于当前已应用的包在程序和功能HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\{应用名}创建卸载入口。实现见 src/Squirrel/UpdateManager.InstallHelpers.cs。它默认使用内置的Update.exe --uninstall静默开关-s作为卸载命令并写入DisplayName、DisplayVersion、Publisher、UninstallString、QuietUninstallString、EstimatedSize、NoModify、NoRepair等键值若包元数据带图标 URL还会下载并转成 ICO 写入DisplayIcon。RemoveUninstallerRegistryEntry()删除上述注册表卸载项src/Squirrel/UpdateManager.InstallHelpers.cs。文档指出这些方法通常由Update.exe调用即框架内部已集成开发者手动调用多用于自定义卸载入口或卸载清理场景。在标准更新流程UpdateApp中框架会自动创建卸载注册表项src/Squirrel/IUpdateManager.cs。典型完整实现安装、更新、卸载与首启将上述内容组合一个覆盖全部五个事件的完整 C# 应用入口如下using System; using Squirrel; static class Program { [STAThread] static int Main(string[] args) { // 必须在启动最早期调用 HandleEvents using (var mgr new UpdateManager(https://example.com/releases)) { SquirrelAwareApp.HandleEvents( onInitialInstall: v { mgr.CreateShortcutForThisExe(); // 桌面 开始菜单快捷方式 mgr.CreateUninstallerRegistryEntry(); // 程序和功能卸载入口 // 可在此注册文件关联、写入初始配置 }, onAppUpdate: v { mgr.CreateShortcutForThisExe(); // 更新后修复快捷方式 }, onAppObsoleted: v { // 旧版本被替换时的清理通常很少需要做事 }, onAppUninstall: v { mgr.RemoveShortcutForThisExe(); // 删除快捷方式 mgr.RemoveUninstallerRegistryEntry(); // 删除卸载注册表项 }, onFirstRun: () { // 不退出继续正常运行例如置位欢迎向导标记 ShowTheWelcomeWizard true; }); } // 正常应用启动逻辑仅当未走任何 Squirrel 事件分支时到达此处 if (ShowTheWelcomeWizard) ShowWelcomeWizard(); RunMainWindow(); return 0; } }测试与验证Squirrel-Aware 检测仓库的测试项目 test/Squirrel.Tests/SquirrelAwareExecutableDetectorTests.cs 提供了检测逻辑的完整验证矩阵可直接参考或复用AtomShellShouldBeSquirrelAware用fixtures/atom.exeVersion Block 方式标记断言GetPESquirrelAwareVersion 1SquirrelAwareViaVersionBlock/SquirrelAwareViaLanguageNeutralVersionBlock分别验证040904B0与000004B0两种语言代码的版本块都能被识别后者用fixtures/SquirrelAwareTweakedNetCoreApp.exeSquirrelAwareViaAssemblyAttribute验证AssemblyMetadata(SquirrelAwareVersion, 1)属性方式NotSquirrelAware/NotSquirrelAwareTestAppShouldNotBeSquirrelAware验证未标记的 EXE如Update.exe、fixtures/NotSquirrelAwareApp.exe返回null。编写完成后你可以用SquirrelAwareExecutableDetector.GetPESquirrelAwareVersion快速自检产物 EXE 是否被正确标记——这是排查为什么我的应用没收到 Squirrel 事件的首选手段。常见问题排查标记后没有快捷方式确认是否在onInitialInstall/onAppUpdate中调用了CreateShortcutForThisExe或等效的CreateShortcutsForExecutable。标记 Squirrel-Aware 后自动快捷方式已关闭。事件回调没被触发检查 EXE 是否真的带SquirrelAwareVersion 1C# 用属性、原生用 Version Block语言代码必须是040904B0或000004B0确认目录下的 EXE 文件名没有squirrel.前缀且是标准 PE。回调后应用没退出除onFirstRun外的四个回调返回后框架会强制Environment.Exit(0)若你的代码在此之前启动了后台线程或打开了窗口应主动尽快返回。卸载不干净在onAppUninstall中务必对称清理onInitialInstall创建的所有东西快捷方式、注册表项、文件关联。延伸阅读Custom Squirrel Events for non-C# Apps非 C# 应用的自定义 Squirrel 事件 — 原生应用的 Squirrel-Aware 标记与命令行参数处理详解Update Manager更新管理器 —UpdateManager的完整 API 与更新流程Install Process安装过程 — 安装时Update.exe与应用的完整交互时序Update Process更新过程 — 更新时事件触发顺序应用签名Application Signing — 修改 Version Block 资源时需要注意的签名问题。赞分享开发工具【免费下载链接】Squirrel.WindowsAn installation and update framework for Windows desktop apps项目地址https://gitcode.com/gh_mirrors/sq/Squirrel.Windows点击查看免费下载相关推荐TypiCMS菜单系统完全指南从基础配置到高级嵌套导航实现TypiCMS菜单系统完全指南从基础配置到高级嵌套导航实现 TypiCMS作为一款基于Laravel构建的多语言CMS系统其菜单系统是构建网站导航结构的核心ExplorerPatcher安装卸载完整生命周期管理ExplorerPatcher安装卸载完整生命周期管理 概述 ExplorerPatcher是一款革命性的Windows系统增强工具旨在恢复和改进Windo桌面应用系统编程Mongood部署指南客户端与服务端两种模式任选Mongood部署指南客户端与服务端两种模式任选 Mongood是一款基于Fluent Design设计的MongoDB图形化管理工具为开发者提供了现代化、创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。