Windows 程序自动更新方案: Squirrel.Windows

Windows 程序自动更新方案: Squirrel.Windows 1. Squirrel

Squirrel 是一组工具和适用于.Net的库,用于管理 Desktop Windows 应用程序的安装和更新. Squirrel 对 Desktop Windows 应用程序的实现语言没有任何要求.

2. 下载相关工具

Squirrel.Windows

Nuget Commandline

rcedit

Resource Hacker: 可选, 用于查看可执行文件的资源.

3. 环境准备

解压下载的 Squirrel.Windows.zip 文件.

因为 Squirrel.Windows 中自带的 rcedit.exe 是比较老的版本, 不支持中文字符集,所以需要下载最新的 rcedit.exe 文件覆盖到 Squirrel.Windows 目录中.

将 nuget.exe 、rcedit.exe 及 Squirrel.exe 所在文件夹加入到环境变量 Path 中,方便命令行使用

Squirrel.exe 通过 调用 NativeMethods.VerQueryValue 方法在可执行文件的版本资源(BLOCK "040904B0") 中查找 SquirrelAwareVersion 信息. 若存在该值且大于等于1, 则认为该程序为 SquirrelAwareApp. 但是 dotnet5 可执行文件的 VersionInfo 存储在 BLOCK "000004b0" 中, 所以 Squirrel 的 SquirrelAware 功能暂时不支持 dotnet5 应用.

有人已经提交了修复该问题的 PR , 截止到现在该 PR 尚未合并. 为解决 dotnet5 程序里面 SquirrelAwareVersion 的问题, 需要自己通过修改源码重新发布 Squirrel.exe 的方式来增加 dotnet5 的支持. 另外一种更简单的方法是通过 DnSpy 反编译修改 Squirrel.SquirrelAwareExecutableDetector.GetVersionBlockSquirrelAwareValue() 方法, 修改后如下:

int fileVersionInfoSize = NativeMethods.GetFileVersionInfoSize(executable, IntPtr.Zero); if (fileVersionInfoSize <= 0 || fileVersionInfoSize > 4096) { return null; } byte[] array = new byte[fileVersionInfoSize]; if (!NativeMethods.GetFileVersionInfo(executable, 0, fileVersionInfoSize, array)) { return null; } IntPtr intPtr; int num; if (!new string[] { "040904B0", "000004B0" }.Any((string languageCode) => NativeMethods.VerQueryValue(array, "\\StringFileInfo\\" + languageCode + "\\SquirrelAwareVersion", out intPtr, out num))) { return null; } return new int?(1); 4. 使用 Squirrel 发布更新包及安装包

准备好需要集成自动更新的程序.

创建一个 bin 文件夹,将可执行 exe 文件及所有依赖文件拷贝进去.

可选: 使用 rcedit 设置可执行文件的 version string.

设置完成后可以通过 Resource Hacker 查看是否正确设置.(如果设置该项, 需要自己处理 Squirrel 事件来创建桌面快捷方式. 如果不设置,会自动查找所有的 .exe 文件,并建立快捷方式)

rcedit ./bin/MyApp.exe --set-version-string "SquirrelAwareVersion" "1"

创建并修改 .nuspec 文件.

<?xml version="1.0" encoding="utf-8"?> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <!--包名、应用安装位置名称--> <id>MyApp</id> <version>2.0.0</version> <!--快捷方式名称、windows应用管理器中的应用名称--> <title>包装确认台</title> <authors>SanHua Inc.</authors> <requireLicenseAcceptance>false</requireLicenseAcceptance> <description>XXX包装确认台.</description> <!--指定 codepage 支持中文字符--> <language>zh-CN</language> </metadata> <files> <!--Squirrel.Windows默认使用 lib\net45\ 目录作为 app 所在文件夹--> <file src="http://www.likecs.com/bin\**" target="lib\net45\" /> </files> </package>

使用 nuget 命令进行打包

nuget pack MyApp.nuspec

使用 Squirrel 命令发布更新包.

可以通过 -icon -setupIcon 选项来指定图标

Squirrel --releasify MyApp.2.0.0.nupkg -icon favicon.ico -setupIcon favicon.ico

Releases 目录

Squirrel --releasify命令成功执行后会生成一个 Releases 文件夹. 该文件夹下的内容需要保留, 用于下次发布时生成 *-delta.nupkg 增量更新包.

- RELEASES # 该文件记录了各个版本包的名称、hash、大小 - Setup.exe # 提供给用户的 exe 安装包 - Setup.msi # 提供给用户的 msi 安装包 - MyApp-2.0.0-full.nupkg # 基础包 - MyApp-2.0.1-full.nupkg # 全量更新包 - MyApp-2.0.1-delta.nupkg # 增量更新包

app 安装目录

用户安装 app 后, 安装位置为 %LocalAppData%\MyApp, 目录结构如下:

- RELEASES # 该文件记录了各个版本包的名称、hash、大小 - SquirrelSetup.log # Squirrel 运行日志 - Update.exe # Squirrel.exe 的拷贝, 用于执行 Squirrel 命令来实现应用的更新、卸载、创建快捷方式等等 - MyApp.exe # StubExecutable.exe 的拷贝, 该 c++ 程序查找 ./app-x.y.z 目录下与自己同名的 exe - # 通过启动新进程来调用最新版的 app.exe , 比如 app-2.0.1/MyApp.exe - # 创建的桌面快捷方式指向的就是它 - app-2.0.0/** # 上个版本 app 安装位置 - app-2.0.1/** # 最新版本 app 安装位置 5. 使用 Squirrel 进行自动更新

将 RELEASES 、*-full.nupkg、 *-delta.nupkg 文件托管到静态文件服务器上.

通过调用Update.exe --UpdateUrl remoteUrl来实现自动更新.

Squirrel 事件

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwwwxp.html