NetSparkle is a C#, cross-platform, highly-configurable software update framework with pre-built UI for .NET developers compatible with .NET 4.6.2/.NET 6+, WinForms, WPF, and Avalonia; uses Ed25519 signatures. View basic usage here in the README and try the samples for yourself.
NetSparkle 是一个高度可配置的 C# 软件更新框架,兼容 .NET 6+ 和 .NET Framework 4.6.2+,为 .NET Framework(WinForms、WPF)和 .NET 6+(WinForms、WPF、Avalonia)提供了预构建的用户界面,采用 Ed25519 或其他加密签名,甚至允许自定义用户界面或完全不使用内置用户界面!您只需在互联网上某处提供一个包含更新和版本信息的应用程序播客,以及 Markdown 或 HTML 格式的发行说明。该库随后会帮助您检查更新、向用户显示发行说明,并提供下载/安装软件新版本的选项。
内置支持的更新下载类型:
- Windows -- .exe、.msi、.msp
- macOS -- .tar、.tar.gz、.zip、.pkg、.dmg
- Linux -- .tar.gz、.deb、.rpm
有关主要版本变更、更新等信息,请参阅 UPGRADING.md。
入门指南
安装 NetSparkle
NetSparkle 可通过 NuGet 获取。选择 NuGet 包时请注意:
- 若无需内置 UI 且可自行管理相关事务,请引用核心
NetSparkleUpdater.SparkleUpdater package - 若需要内置 UI,或希望基于其他 UI 创建自己的界面,请选择其他包
| 包 | 用途 | 正式版 | 预览版 | 下载量 |
|---|---|---|---|---|
| NetSparkleUpdater.SparkleUpdater | 核心包;使用 100% 自定义 UI 或无 UI(无内置组件) | |||
| WinForms UI (.NET Framework) | 带内置 WinForms UI 的 NetSparkle | |||
| WinForms UI (.NET 6+) | 带内置 WinForms UI 的 NetSparkle | |||
| WPF UI (.NET Framework and .NET 6+) | 带内置 WPF UI 的 NetSparkle | |||
| Avalonia UI | 带内置 Avalonia UI 的 NetSparkle | |||
| App Cast Generator Tool | netsparkle-generate-appcast CLI 工具(含 Ed25519 辅助功能) |
|||
| DSA Helper Tool | netsparkle-dsa CLI 工具(DSA 辅助功能) |
工具安装快速说明:
- App cast 生成器 --
dotnet tool install --global NetSparkleUpdater.Tools.AppCastGenerator;安装后可在命令行中使用netsparkle-generate-appcast命令 - DSA 辅助工具 --
dotnet tool install --global NetSparkleUpdater.Tools.DSAHelper;安装后可在命令行中使用netsparkle-dsa命令
更新工作原理
典型软件的软件更新流程通常如下:
- 编译应用程序,使其可在其他计算机上运行(例如
dotnet publish) - 开发人员将应用程序放入某种安装程序/压缩包等中进行分发(例如 Windows 平台的 InnoSetup)
- 开发人员创建应用播客文件(有关如何创建的更多信息,请参阅本文档的应用播客部分)
- 开发人员将分发文件(安装程序、应用播客文件、appCast-file.signature 文件)上传到其下载站点。
- 客户端打开应用程序,并自动收到可用更新的通知(或软件以其他方式检测到存在更新)
- 客户端选择更新(或如果软件自动下载更新,则更新会被下载)
- 更新已下载并保存在用户的磁盘上
- 系统会要求用户关闭软件以便运行更新。用户关闭软件。
- 运行下载的文件/安装程序(或以其他方式执行更新)
目前,NetSparkleUpdater 不 帮助您完成步骤 1.、2. 或 4.。您可能会问:“为什么不呢?”
-
- 我们无法为您编译应用程序,因为我们不知道(也不关心)您是如何编译或打包应用程序的! 😃
-
- 跨平台安装程序包/系统实现起来难度较大,而且可能给最终用户带来不常规的体验,不过我认为使用 Avalonia 的系统或许可行(尽管可能需要大量工作,并且会使下载文件变大!)。我们不提供准备安装程序/分发的支持。要生成安装程序/分发,我们建议如下:
- Windows:InnoSetup 或 NSIS 或 WiX
- macOS:如果要分发 .app,可将 dotnet-bundle 与 create-dmg 配合使用。如果需要安装程序,可使用 macos-installer-builder(教程见此处)、Packages 或终端 创建 .pkg 安装程序。否则,直接将文件打包成 zip 文件即可。如果出于某种原因需要使用
sudo运行,macOSAvalonia示例中有相关操作示例。 - Linux:使用 dotnet-packaging 为用户创建 rpm、deb 或 tar.gz 文件。
-
- 我们不知道您的文件将存放在互联网的哪个位置,因此您需要负责将这些文件上传并放到在线的某个位置。
要创建应用播客文件,请参阅本文档的应用播客部分。
我们欢迎能让用户整体安装/更新过程更轻松的贡献。例如,添加从应用播客生成器上传到 FTP 或 GitHub 发布版等功能,可能对部分用户有用。请在开始工作前先提交 issue 说明您的想法,以便我们进行讨论。
基本用法
请查看此仓库中的示例项目,获取基本的、可运行的使用示例! 其中包含使用各个内置 UI 的示例,以及一个“在您自己的 UI 中自行实现”的示例!
快速入门
- 如果您需要预构建的 UI,请安装其中一个 UI NuGet 包。如果不需要,则安装核心 NuGet 包。
- 按照下一节中的说明设置您的项目文件
- 下载应用播报生成器 CLI 工具(需要 .NET 6、7、8 或 9 运行时):
dotnet tool install --global NetSparkleUpdater.Tools.AppCastGenerator - 创建您的 ed25519 密钥(将生成的密钥保存在安全的地方!):
netsparkle-generate-appcast --generate-keys
# By default, your Ed25519 signatures are stored on disk in your local
# application data folder in a subdirectory called `netsparkle`.
# If you want to export your keys to the console, you can do:
netsparkle-generate-appcast --export
- 在您的
MainWindow或主窗体等类似位置添加如下代码:
private SparkleUpdater _sparkle;
// on your main thread...
_sparkle = new SparkleUpdater(
"https://mywebsite.com/appcast.xml", // link to your app cast file - change extension to .json if using json
new Ed25519Checker(SecurityMode.Strict, // security mode -- use .Unsafe to ignore all signature checking (NOT recommended!!)
"base_64_public_key_from_generate_app_cast_tool") // your base 64 public key
) {
UIFactory = new NetSparkleUpdater.UI.WPF.UIFactory(icon), // or null, or choose some other UI factory, or build your own IUIFactory implementation!
RelaunchAfterUpdate = false, // set to true if needed
};
_sparkle.StartLoop(true); // will auto-check for updates
- 构建你的项目
- 如有需要,创建一个变更日志文件(Markdown 格式)
- 使用
InnoSetup(Windows)、DMG 文件(macOS)、.tar.gz 文件(Linux)或类似工具为你的项目创建安装程序。更多信息请参见更新工作原理部分。 - 运行应用程序广播生成器(有关选项,请参阅本 README 的其他部分或
netsparkle-generate-appcast --help):netsparkle-generate-appcast -b binary/folder -p change/log/folder -u https://example.com/downloads -l https://example.com/downloads/changelogs - 将你的文件(包括任何
.signature或类似文件)上传到服务器上的相应位置 - 通过使用比刚上传的版本更低的临时软件版本重新构建项目来进行测试运行。NetSparkle 应会检查更新,发现存在更新,并为你/与你一起完成更新过程(当然,这取决于你是否使用内置 UI)。
- 遇到问题?第一步是使用
SparkleUpdater.LogWriter,查看控制台是否显示任何有用的调试信息!
项目文件
在你的项目文件中,请确保设置一些内容,以便库稍后能够读取相关详细信息。注意:你可以使用自己的 IAssemblyAccessor 从其他地方加载版本信息。不过,在项目文件中进行设置非常简单,NetSparkleUpdater 可以原生读取这些信息!
<PropertyGroup>
<Version>1.0.2-beta1</Version> <!-- accepts semver -->
<AssemblyVersion>1.0.2</AssemblyVersion> <!-- only accepts Major.Minor.Patch.Revision -->
<AssemblyTitle>My Best App</AssemblyTitle>
<!-- When using AssemblyDiagnosticsAccessor, accessor.AssemblyTitle is actually the
<Product> information due to limitations with the way the diagnostics access works -->
<Description>My app is cool (not required)</Description>
<Company>My Company Name (required unless you set the IAssemblyAccessor save path yourself)</Company>
<Product>My Product (required unless you set the IAssemblyAccessor save path yourself; set to product name e.g. MyBestApp)</Product>
<Copyright>2025 MyCompanyName</Copyright>
</PropertyGroup>
重要注意事项:在 .NET 8+ 中,.NET 核心部分进行了一项更改,导致你的 git/源代码提交哈希会被包含在应用的 <Version> 号中。目前 NetSparkleUpdater 无法避免此行为,因为我们依赖 AssemblyInformationalVersionAttribute,而此属性的行为已发生变更。NetSparkleUpdater(以及你的原生应用本身)可能会告知用户他们当前正在运行 1.0.0+commitHashHere 版本。我们还建议在项目文件中添加以下行(在新的 <PropertyGroup> 或现有 <PropertyGroup> 中):
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
可用的 NetSparkle 示例
- NetSparkle.Samples.Avalonia - 基础 Avalonia 示例
- NetSparkle.Samples.Avalonia.MacOS - macOS 平台的基础 Avalonia 示例,展示如何以管理员身份打开更新
- NetSparkle.Samples.Avalonia.MacOSZip - macOS 平台的 Avalonia 示例,用于下载并解压 zip 文件更新,然后启动应用
- NetSparkle.Samples.Avalonia.Rollback - 展示回滚功能、操作系统架构筛选以及在后台下载可用更新以自行回滚项目的 Avalonia 示例
- NetSparkle.Samples.DownloadedExe - 并非真正的示例。这是其他一些示例所下载的小型图形界面程序。
- NetSparkle.Samples.Forms.Multithread - Windows WinForms 示例,演示如何在自定义线程模型(在本示例中,每个窗口对应一个 UI 线程)上运行 NetSparkle
- NetSparkle.Samples.HandleEventsYourself - 展示如何仅使用核心库并自行处理事件来实现用户界面的示例
- NetSparkle.Samples.NetCore.WinForms - .NET 平台上用于 WinForms 的简单界面示例
- NetSparkle.Samples.NetCore.WPF - .NET 平台上用于 WPF 的简单界面示例
- NetSparkle.Samples.NetFramework.WinForms - .NET Framework 平台上用于 WinForms 的简单界面示例
- NetSparkle.Samples.NetFramework.WPF - .NET Framework 平台上用于 WPF 的简单界面示例
- NetSparkle.Samples.SimpleConsoleApp - 并非真正的示例。这是 Avalonia.Rollback 示例所下载的控制台应用程序。
代码
// NOTE: Under most, if not all, circumstances, SparkleUpdater should be initialized on your app's main UI thread.
// This way, if you're using a built-in UI with no custom adjustments, all calls to UI objects will automatically go to the UI thread for you.
// Basically, SparkleUpdater's background loop will make calls to the thread that the SparkleUpdater was created on via SyncronizationContext.
// So, if you start SparkleUpdater on the UI thread, the background loop events will auto-call to the UI thread for you.
_sparkle = new SparkleUpdater(
"http://example.com/appcast.xml", // link to your app cast file
new Ed25519Checker(SecurityMode.Strict, // security mode -- use .Unsafe to ignore all signature checking (NOT recommended!!)
"base_64_public_key") // your base 64 public key -- generate this with the NetSparkleUpdater.Tools.AppCastGenerator .NET CLI tool on any OS
) {
UIFactory = new NetSparkleUpdater.UI.WPF.UIFactory(icon), // or null, or choose some other UI factory, or build your own IUIFactory implementation!
RelaunchAfterUpdate = false, // default is false; set to true if you want your app to restart after updating (keep as false if your installer will start your app for you)
CustomInstallerArguments = "", // set if you want your installer to get some command-line args
};
_sparkle.StartLoop(true); // `true` to run an initial check online -- only call StartLoop **once** for a given SparkleUpdater instance!
在首个 Application.Idle 事件触发时,系统会下载、读取你的 App Cast XML 文件,并将其与当前运行版本进行比较。若文件中包含软件更新,系统将通过小型弹窗通知(若 UI 支持且已启用)或带有发行说明的更新对话框提醒用户。用户可选择忽略更新、稍后提醒,或立即下载/安装更新。
如果希望在后台检查更新而不向用户显示任何内容,请使用
var updateInfo = _sparkle.CheckForUpdatesQuietly();
如果您希望添加一个菜单项,让用户能够手动检查更新,以便用户在 NetSparkle 查找更新时可以看到用户界面,请使用
_sparkle.CheckForUpdatesAtUserRequest();
如果您有需要保存的文件,请订阅 PreparingToExit 事件:
_sparkle.PreparingToExit += ((x, cancellable) =>
{
// ask the user to save, whatever else is needed to close down gracefully
});
请注意,如果你不使用 UIFactory,则必须使用 CloseApplication 或 CloseApplicationAsync 事件来关闭应用程序;否则,下载的更新文件将永远不会被执行/读取!唯一的例外是你希望自行处理更新包安装的所有方面。
启动下载的更新可执行文件的程序只会等待 90 秒,之后便会放弃!如果你实现了 CloseApplication/CloseApplicationAsync 事件,请确保软件能在这些事件被调用后的 90 秒内关闭!如果你需要一个可取消的事件(例如,当需要询问用户是否可以关闭应用程序时,比如为了保存他们的工作),请使用 PreparingForExit 或 PreparingToExitAsync。
我可以利用哪些接口和类来根据自己软件的需求配置功能?
接口
- 如果你想使用自己的 UI,请实现
IUIFactory;设置SparkleUpdater.UIFactory以使用你的对象实例。- 为你的 UI 实现
ICheckingForUpdates,用于告知用户SparkleUpdater正在检查更新 - 为你的 UI 实现
IDownloadProgress,用于向用户显示更新正在下载的进度 - 为你的 UI 实现
IUpdateAvailable,用于向用户显示有更新可用以及发行说明
- 为你的 UI 实现
- 实现
IAppCastDataDownloader以设置自己的方法来下载应用程序广播(app cast)数据;设置SparkleUpdater.AppCastDataDownloader以使用你的对象实例。NetSparkle 默认包含两个实现:WebRequestAppCastDataDownloader用于从互联网下载应用程序广播信息,LocalFileAppCastDownloader用于从指定路径复制/“下载”应用程序广播。 - 实现
IAppCastFilter以对下载的应用程序广播中的AppCastItem对象进行自定义过滤,例如,只将特定子集的项目视为应用程序的有效更新;设置AppCastHelper.AppCastFilter(SparkleUpdater.AppCastHelper.AppCastFilter)以使用你的对象实例。NetSparkle 包含ChannelAppCastFilter类,如果你在应用程序中使用了产品通道(如 alpha、beta),可以使用此类按指定的产品通道过滤项目。 - 实现
IAppCastGenerator以控制应用程序广播的序列化和反序列化方式;设置SparkleUpdater.AppCastGenerator以使用你的对象实例。NetSparkle 包含两个实现:XMLAppCastGenerator用于 XML 序列化/反序列化;JsonAppCastGenerator用于 JSON 序列化/反序列化。应用程序广播生成器 CLI 工具也可以输出 XML 和 JSON 格式的应用程序广播。 - 实现
IAssemblyAccessor以控制如何为应用程序加载版本、版权和其他产品详细信息;设置Configuration.AssemblyAccessor(SparkleUpdater.Configuration.AssemblyAccessor)以使用你的对象实例。NetSparkle 包含一个默认实现AssemblyDiagnosticsAccessor,它在从指定程序集加载数据的一般情况下应该可以正常工作。 - 要将信息记录到文件或控制台,请实现
ILogger并设置SparkleUpdater.LogWriter。默认情况下,使用LogWriter类(它具有LogWriterOutputMode属性,用于控制日志是写入Console、Trace等)。 - 实现
ISignatureVerifier以更改应用程序广播、下载等的签名处理方式;设置SparkleUpdater.SignatureVerifier以使用你的对象实例。 - 实现
IUpdateDownloader以设置自己的方法来下载应用更新文件(如安装程序)并发送给定应用程序广播项的进度;设置SparkleUpdater.UpdateDownloader以使用你的对象实例。NetSparkle 默认包含两个实现:WebFileDownloader(默认)用于从网络/互联网下载文件,LocalFileDownloader用于从指定路径复制/“下载”文件。
子类化
- 子类化
Configuration以更改 NetSparkle 某些信息的保存和加载方式——例如,已跳过的版本信息。此类利用IAssemblyAccessor实例来保存和加载版本信息、产品名称等。NetSparkle 包含三个实现:RegistryConfiguration,将信息保存和加载到 Windows 注册表(Windows 上的默认值);JSONConfiguration,将信息保存和加载到 JSON 文件(macOS/Linux 上的默认值);以及DefaultConfiguration,它不执行任何操作,在JSONConfiguration无法找到有效的文件位置来保存和加载数据时作为回退。要使用你的类实例,请设置SparkleUpdater.Configuration。- 子类化
RegistryConfiguration可以通过BuildRegistryPath快速更改保存项目的注册表路径 - 子类化
JSONConfiguration可以通过GetSavePath快速更改保存数据的文件路径
- 子类化
- 如果你想完全控制应用程序广播的下载和解析过程,可以子类化
AppCastHelper。请注意,你可能可以通过AppCastHelper的属性(包括IAppCastFilter AppCastFilter)完成所有需要的操作,但子类化将使你对整个过程拥有完全、绝对的控制权。要使用你的类实例,请设置SparkleUpdater.AppCastHelper。 - 子类化
ReleaseNotesGrabber以控制发行说明的下载(从而控制显示)过程。要使用你的类实例,请设置UIFactory.ReleaseNotesGrabberOverride。 - 如果你不想自己实现
IUpdateDownloader,而只想重写一两个函数,例如CreateHttpClient或RetreiveDestinationFileNameAsync,可以重写WebFileDownloader。要使用你的类实例,请设置SparkleUpdater.UpdateDownloader。 - 如果你不想实现
IAppCastDataDownloader,而只想重写一两个函数,例如CreateHttpClient,可以重写WebRequestAppCastDataDownloader。要使用你的类实例,请设置SparkleUpdater.AppCastDataDownloader。 - 重写
LogWriter以实现PrintMessage函数;由于ILogger是一个非常简单的接口,如果你的需求复杂,你可能只需自己实现该接口。要使用你的类实例,请设置SparkleUpdater.LogWriter。 - 重写
SparkleUpdater以实现一些不同的安装相关函数,包括:GetWindowsInstallerCommandGetInstallerCommandRunDownloadedInstallerGetDownloadPathForAppCastItem
- 如果你不想自己实现整个
IUIFactory接口,而只想配置一两个函数,可以重写UIFactory。要使用你的类实例,请设置SparkleUpdater.UIFactory。
使用 IAppCastFilter
你可以通过 AppCastHelper.AppCastFilter 属性(通过 IAppCastFilter 接口)更改应用程序广播项的过滤方式。这允许你更改哪些项目对最终用户可用。
NetSparkle 包含一个内置的基于通道过滤的 IAppCastFilter 实现,名为 ChannelAppCastFilter。有关如何使用该类的一些示例,请参见此处的单元测试。基本上,将 List<string> ChannelSearchNames 属性设置为你要过滤的通道。如果你想保留没有通道信息的项目(例如 1.2.3),请将 KeepItemsWithNoChannelInfo 设置为 true。
要在应用程序广播项/应用程序广播中实际设置通道,请使用应用程序广播 CLI 工具的 --channel 属性,或将项目文件的 <Version> 属性设置为适用的 semver 兼容版本(例如 <Version>1.0.2-beta1</Version>),应用程序广播 CLI 工具将自动识别此版本。或者,如果你手动构建应用程序广播,请在 <item> 上设置 <sparkle:channel>YourChannelHere</sparkle:channel> 属性(如果使用 JSON,则设置 channel 属性)。
使用/构建你自己的 UI
NetSparkleUpdater 完全可以不与 UI 一起使用。你可以自己完成所有操作,甚至通过设置 SparkleUpdater.UserInteractionMode = UserInteractionMode.DownloadAndInstall 让库自动运行下载的更新。此仓库中有一个示例,展示了如何在没有任何预构建 UI 的情况下自行处理事务,位于 src/NetSparkle.Samples.HandleEventsYourself。
如果你需要 UI,我们在不同的 NuGet 包中提供了预构建的 UI,针对 WinForms、WPF 和 Avalonia 有少量可自定义选项。这些 UI 通过 IUIFactory 实现触发,在每个内置选项中都称为 UIFactory。UIFactory 中的大多数方法都可以重写以调整行为,ProcessWindowAfterInit 允许你在每个窗口创建后对其进行自定义。
如果你想完全自定义自己的 UI,只需使用你想要的任何 UI 库实现 IUIFactory 接口。你可以从 NetSparkleUpdater 的预构建选项中复制或重用视图模型、代码等,将此仓库中的代码复制粘贴到你自己的项目中可能是一个快速入门的好方法。不过,不要忘记使用你的 IUIFactory 实现实例设置 SparkleUpdater.UIFactory 属性!
请注意:NetSparkle 基本上不会尝试处理线程问题(例如调用主线程),除非后台循环调用启动 SparkleUpdater 实例的主线程。换句话说,一般而言,NetSparkle 会在最初创建 SparkleUpdater 实例的线程上执行所有操作。对于大多数应用程序来说,这没问题,因为它们只使用主 UI 线程。如果有疑问,为了你自己的 UI 需求,请确保在 WinForms 上检查 InvokeRequired,在 WPF/Avalonia 上,将操作编组到 UI 线程(除非你使用数据绑定,在这种情况下会自动处理!)。
将你自己的 IUIFactory 实现(会在新线程上启动窗口/内容)传递给 SparkleUpdater 不是受支持的配置。如果你想在多个线程上运行自己的 UI(例如,为了让 WinForms 中的 NetSparkleUpdater 窗口在主窗体关闭时不关闭),请使用 SparkleUpdater 的事件,而不是 UIFactory;另请参见 src/NetSparkle.Samples.Forms.Multithread 示例,了解如何执行此操作的实际示例。
应用程序广播(App cast)
应用程序广播是一个 XML 或 JSON 文件。它包含诸如产品标题、描述以及软件每个版本的定义等字段。
我们强烈建议您使用 netsparkle-generate-appcast 工具来创建(以及后续重新创建/更新)该文件,因为它可以帮助您处理所有签名要求。
安装应用程序广播生成工具
- 此工具需要安装 .NET 6、7、8 或 9 桌面运行时。
dotnet tool install --global NetSparkleUpdater.Tools.AppCastGenerator- 现在,您可以在命令行中使用
netsparkle-generate-appcast命令调用该工具。您可以使用netsparkle-generate-appcast --help查看该工具的所有选项。
Sparkle 兼容性
默认情况下,NetSparkle 在很大程度上使用与 Sparkle 兼容的 XML 应用程序广播。NetSparkle 使用 sparkle:signature 而非 sparkle:edSignature,以便您可以选择如何为文件/应用程序广播签名。(如果您希望使用 sparkle:edSignature,请向应用程序广播生成器传递 --use-ed25519-signature-attribute 参数。)请注意,NetSparkle 默认兼容并使用 Ed25519 签名,但该框架可以通过 ISignatureVerifier 类的不同实现来检查不同类型的签名,而无需进行重大版本更新。
应用程序广播示例
以下是一个 XML 应用程序广播示例:
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
<channel>
<title>NetSparkle Test App</title>
<link>https://netsparkleupdater.github.io/NetSparkle/files/sample-app/appcast.xml</link>
<description>Most recent changes with links to updates.</description>
<language>en</language>
<item>
<title>Version 2.0 (2 bugs fixed; 3 new features)</title>
<sparkle:releaseNotesLink>
https://netsparkleupdater.github.io/NetSparkle/files/sample-app/2.0-release-notes.md
</sparkle:releaseNotesLink>
<pubDate>Thu, 27 Oct 2016 10:30:00 +0000</pubDate>
<enclosure url="https://netsparkleupdater.github.io/NetSparkle/files/sample-app/NetSparkleUpdate.exe"
sparkle:version="2.0"
sparkle:os="windows"
length="12288"
type="application/octet-stream"
sparkle:signature="NSG/eKz9BaTJrRDvKSwYEaOumYpPMtMYRq+vjsNlHqRGku/Ual3EoQ==" />
</item>
</channel>
</rss>
应用更新信息项
NetSparkle 通过读取 <item> 标签来判断是否有可用更新。
每个 <item> 中的重要标签如下:
<description>- 更新的 HTML 或 Markdown 格式描述。
- 会覆盖
<sparkle:releaseNotesLink>标签。
<sparkle:releaseNotesLink>- 指向描述更新的 HTML 或 Markdown 文档的 URL。
- 如果存在
<description>标签,则会优先使用该标签。 - 属性:
sparkle:signature(可选):文档的 DSA/Ed25519 签名;除非将ReleaseNotesGrabber.ChecksReleaseNotesSignature设置为true,否则 NetSparkle 不会为您检查此签名,但您可以手动验证更新日志签名,或者在您的 UI 中将ReleaseNotesGrabber.ChecksReleaseNotesSignature设置为true。
<pubDate>- 此更新的发布日期
sparkle:channel:此应用更新信息项的渠道,例如beta(非必需)- 仅接受一个渠道<enclosure>- 此标签描述 NetSparkle 将下载的更新文件。
- 属性:
url:更新文件的 URLsparkle:version:此更新的机器可读版本号length(可选):(未验证)更新文件的大小(以字节为单位)type:忽略sparkle:signature:更新文件的 DSA/Ed25519 签名sparkle:criticalUpdate(可选):如果值为true或1,UI 将指示这是一个重要更新sparkle:os:应用更新信息项适用的操作系统。如果未提供,默认为 Windows。Windows 系统使用 "win" 或 "windows";macOS 系统使用 "macos" 或 "osx";Linux 系统使用 "linux"。
默认情况下,您需要 2 个签名(SecurityMode.Strict):
- 一个在 enclosure 标签中,用于更新文件(
sparkle:signature="...") - 另一个在您的 Web 服务器上,用于保护实际的应用更新信息文件。此文件必须位于 [AppCastURL].signature。换句话说,如果应用更新信息 URL 是 http://example.com/awesome-software.xml,那么您需要在 http://example.com/awesome-software.xml.signature 处提供该文件的有效(DSA/Ed25519)签名。
注意: 当应用更新信息生成工具重新创建 appcast.xml 文件时,会为您创建这两个签名。
Ed25519 签名
您可以使用 AppCastGenerator 工具(来自 此 NuGet 包 或 此处的源代码)生成 Ed25519 签名。此工具需要安装 .NET 6、7、8 或 9 桌面运行时。 请参阅以下部分,了解生成 Ed25519 密钥的选项和示例,以及在创建应用程序广播时如何使用它们。
如何制作应用程序广播?
- 使用
AppCastGenerator工具(来自 此 NuGet 包 或 此处的源代码)轻松创建您的应用程序广播文件。下面描述了可用选项。您可以通过dotnet tool install --global NetSparkleUpdater.Tools.AppCastGenerator在 CLI 上安装它。 - 编写一个脚本,用 python 或其他语言为您生成应用程序广播(
string.Format或类似功能非常有用)。 - 或者,您可以将上面的应用程序广播示例复制粘贴到您自己的文件中,自行调整签名/下载信息,然后手动为应用程序广播文件生成(Ed25519/DSA)签名! 😃
使用 JSON 应用程序广播
如果您想使用 JSON 应用程序广播而不是 XML:
- 通过应用程序广播生成器生成应用程序广播文件时,使用
--output-type json - 将
SparkleUpdater.AppCastGenerator设置为new JsonAppCastGenerator(mySparkleUpdater.LogWriter)。 - 默认情况下,输出是人类可读的。如果要关闭此功能,请将
JsonAppCastGenerator.HumanReadableOutput属性设置为false。
应用程序广播生成器选项
缺少您想要的某些选项?在此仓库上提交 issue,或者自己添加并向我们发送拉取请求!
--show-examples:将使用示例打印到控制台。--help:显示所有选项及其描述。
生成应用程序广播时的常规选项
-a/--appcast-output-directory:用于写入输出appcast.xml文件的目录。示例用法:-a ./MyAppCastOutput-e/--ext:查找要添加到应用程序广播的文件时,使用给定的扩展名。默认为exe。示例用法:-e exe,msi-b/--binaries:应搜索以查找要添加到应用程序广播的文件的目录的文件路径。默认为.。示例用法:-b my/build/directory-r/--search-binary-subdirectories:为true时递归搜索二进制目录以查找二进制文件;为false时仅搜索顶级目录。默认为false。示例用法:-r。--single-file:要添加到应用程序广播的单个文件 - 如果设置,--binaries、--ext等都将被忽略。如果您的输出文件没有扩展名(例如,是 Unix 可执行文件),使用此选项会很有帮助。示例用法:--single-file path/to/my/file-f/--file-extract-version:是否从文件名而不是文件(例如 dll)本身提取文件的版本。默认为false。当 NetSparkleUpdater 将下载的文件的文件名中包含版本号时使用,例如 "My App 1.3.2-alpha1.exe"。请注意,这仅搜索最后四个目录项/文件夹。示例用法:-f true--file-version:用于为要进入应用程序广播的二进制文件设置版本。请注意,此版本只能设置一次,因此生成应用程序广播时,请确保您要么:A) 应用程序广播中只有一个二进制文件 | B) 利用--reparse-existing参数以便获取旧项目。如果生成器找到 2 个没有已知版本的二进制文件,并且设置了--file-version,则会发出错误。示例用法:--file-version 1.3.2-o/--os:应用程序广播项目所属的操作系统。字符串必须包含以下之一:windows、mac、linux。默认为windows。示例用法:-o macos-arm64;-o windows-x64--description-tag:要放入应用程序广播描述标签/信息的文本。默认为 "Most recent changes with links to updates"。示例用法:--description-tag "Hello I am a Cool App"--link-tag:要放入应用程序广播link标签/信息的文本。如果使用此选项,它应该是您的应用程序广播下载 URL。示例用法:--link-tag https://mysite.com/coolapp/appcast.xml-u/--base-url:用于下载的 URL 的起始部分。将要下载的文件名将放在此 URL 部分之后。示例用法:-u https://myawesomecompany.com/downloads-l/--change-log-url:用于更改日志文件的 URL 的起始部分。将要下载的更改日志文件将放在此 URL 部分之后。如果未指定此选项,则更改日志数据将被放入应用程序广播本身。示例用法:-l https://myawesomecompany.com/changes-p/--change-log-path:软件更改日志文件的路径。这些文件应为 markdown 格式,扩展名为.md。更改日志文件的文件名必须包含软件的版本,例如1.3.2.md。示例用法:-p path/to/change/logs。(注意:生成器还将尝试查找文件名为以下格式的更改日志:MyApp 1.3.2.md。)--change-log-name-prefix:更改日志文件名的前缀。默认情况下,生成器搜索格式为 "[Version].md" 的文件名。如果您将此参数设置为(例如)"My App Change Log",它将搜索格式为 "My App Change Log [Version].md" 以及 "[Version].md" 的文件名。-n/--product-name:软件的产品名称。用于设置应用程序广播及其项目的标题。默认为Application。示例用法:-n "My Awesome App"-x/--url-prefix-version:将版本号作为前缀添加到下载 URL 的文件名中。默认为 false。例如,如果--base-url是www.example.com/downloads,您的版本是1.4.2,您的应用程序名称是MyApp.exe,您的下载 URL 将变为www.example.com/downloads/1.4.2/MyApp.exe。示例用法:-x true。--key-path:NetSparkle_Ed25519.priv和NetSparkle_Ed25519.pub文件的路径,它们分别是您的软件更新的私钥和公钥 Ed25519 密钥。示例用法:--key-path my/path/to/keys- 如果您想动态使用密钥,可以在运行
generate_appcast之前设置SPARKLE_PRIVATE_KEY和SPARKLE_PUBLIC_KEY环境变量。该工具优先使用环境变量中的密钥,而不是磁盘上的密钥!
- 如果您想动态使用密钥,可以在运行
--signature-file-extension:用于应用程序广播签名文件的扩展名(不带.)。默认为signature。示例用法:--signature-file-extension txt。--output-file-name:应用程序广播的输出文件名,包含.或扩展名。扩展名由输出是 xml 还是 json 控制,不可配置。默认为 'appcast'。当然,您始终可以在生成应用程序广播后自行更改它;此选项仅为方便起见。示例用法:--output-file-name super_app_download_info。--use-ed25519-signature-attribute:如果为 true 且进行 XML 输出,XML 中的输出签名属性将为edSignature,而不是signature,以匹配原始的 Sparkle 库。对 JSON 应用程序广播无影响。--file-version:用于为要进入应用程序广播的二进制文件设置版本。请注意,此版本只能设置一次,因此生成应用程序广播时,请确保您要么:A) 应用程序广播中只有一个二进制文件 | B) 利用--reparse-existing参数以便获取旧项目。如果生成器找到 2 个没有已知版本的二进制文件,并且设置了--file-version,则会发出错误。--critical-versions:要在应用程序广播中标记为关键版本的逗号分隔列表。必须与版本文本完全匹配。例如,"1.0.2,1.2.3.1"。--reparse-existing:重新解析现有的应用程序广播,而不是覆盖它并重新创建。跳过应用程序广播中已有的版本,因此如果您部署具有相同版本的新二进制文件,您需要手动编辑应用程序广播以删除您要重新部署的版本的旧列表。示例用法:--reparse-existing true--overwrite-old-items:如果在磁盘上找到具有相同版本号的二进制文件,则导致应用程序广播项目在应用程序广播中被重写。换句话说,如果 1.0.1 已在应用程序广播中(无论是通过重新解析还是来自另一个二进制文件),并且在磁盘上找到另一个 1.0.1,则应用程序广播中的 1.0.1 数据将基于找到的二进制文件被重写。请注意,这意味着如果您的磁盘上有多个 1.0.1 版本(您不应该这样做...),找到的最后一个版本将是应用程序广播中的版本!示例用法:--overwrite-old-items--human-readable:如果为 true,则使输出的应用程序广播文件人类可读(换行、缩进)。示例用法:--human-readable true--channel:要添加到应用程序广播中的任何项目的发布通道名称。应该是单个通道;不支持同时多个通道,例如beta,gamma。如果要使用发布通道,则不要设置此选项 - 如果将此选项设置为release或stable,这些名称/单词将被视为特殊通道,而不是稳定通道。(当然,除非您希望所有项目都在特定通道中。)示例用法:--channel beta--output-type:应用程序广播文件的输出类型(xml或json)。默认为xml。示例用法:--output-type json
覆盖公钥/私钥
--public-key-override:用于签名二进制文件的公钥覆盖(忽略公钥文件中的任何内容)。这会覆盖验证二进制文件时设置的所有其他公钥,包括通过环境变量设置的公钥!如果未设置,则使用--key-path(如果已设置)或默认的 SignatureManager 位置。不在--generate-keys或--export中使用。示例用法:--public-key-override asoj341ljsdflj--private-key-override:用于签名二进制文件的私钥覆盖(忽略私钥文件中的任何内容)。这会覆盖验证二进制文件时设置的所有其他公钥,包括通过环境变量设置的私钥!如果未设置,则使用--key-path(如果已设置)或默认的 SignatureManager 位置。不在--generate-keys或--export中使用。示例用法:--private-key-override asoj341ljsdflj
密钥生成选项
--generate-keys:如果设置,将尝试为您生成新的 Ed25519 密钥。可以与--key-path结合使用。一旦密钥成功(或失败)生成,程序将结束而不生成应用程序广播。默认情况下,不会覆盖现有密钥。此选项默认为false。--force:如果设置为true,将覆盖磁盘上的现有密钥。警告:这可能导致您的公钥和私钥丢失。请谨慎使用。如果您不知道自己在做什么,请不要使用!这不会尝试备份您的数据。 此选项默认为false。示例用法:--generate-keys --force true。--export:将密钥作为 base 64 字符串导出到控制台。默认为false。示例用法:--export true。输出格式:
Private Key:
2o34usledjfs0
Public Key:
sdljflase;ru2u3
不使用应用广播生成签名的选项
--generate-signature:为文件生成签名并将其输出到控制台。使用示例:--generate-signature path/to/app/MyApp.exe。输出格式:Signature: seljr13412zpdfj。
验证签名的选项
请注意,这些选项仅用于验证 Ed25519 签名。对于 DSA 签名,请使用 DSAHelper 工具。以下两个选项必须一起使用。您必须已生成密钥才能验证文件签名。
--verify:要验证其签名的文件的路径。--signature:文件的 Base 64 签名。
使用示例:--verify my/path/MyApp.exe --signature 123l4ijsdfzderu23。
这将返回 Signature valid(签名有效!)或 Signature invalid(签名与文件不匹配)。
应用广播生成器示例
#### Key Generation
# Generate Ed25519 keys for the first time
netsparkle-generate-appcast --generate-keys
# Store keys in a custom location
netsparkle-generate-appcast --key-path path/to/store/keys
# Pass in public key via command line
netsparkle-generate-appcast --public-key-override [YourPublicKeyHere]
# Pass in private key via command line
netsparkle-generate-appcast --private-key-override [YourPrivateKeyHere]
# By default, your Ed25519 signatures are stored on disk in your local
# application data folder in a subdirectory called `netsparkle`.
# If you want to export your keys to the console, you can do:
netsparkle-generate-appcast --export
# You can also store your keys in the following environment variables:
# set public key: SPARKLE_PUBLIC_KEY
# set private key: SPARKLE_PRIVATE_KEY
#### Generate a signature for a binary without creating an app cast:
netsparkle-generate-appcast --generate-signature path/to/binary.exe
#### Verifying Binaries
netsparkle-generate-appcast --verify path/to/binary.exe --signature base_64_signature
#### Using a custom key location:
# If your keys are sitting on disk somewhere
# (`NetSparkle_Ed25519.priv` and `NetSparkle_Ed25519.pub` -- both
# in base 64 and both on disk in the same folder!), you can pass in
# the path to these keys like this:
netsparkle-generate-appcast --key-path path/to/keys/
#### Generating an app cast
# Generate an app cast for Windows executables that are sitting in a
# specific directory
netsparkle-generate-appcast -a directory/for/appcast/output/ -e exe -b directory/with/binaries/ -o windows
# Add change log info to your app cast
netsparkle-generate-appcast -b binary/folder -p change/log/folder
# Customize download URL for binaries and change logs
netsparkle-generate-appcast -b binary/folder -p change/log/folder -u https://example.com/downloads -l https://example.com/downloads/changelogs
# Set your application name for the app cast
netsparkle-generate-appcast -n "My Awesome App" -b binary/folder
# Use file versions in file names, e.g. for apps like "My App 1.2.1.dmg"
netsparkle-generate-appcast -n "macOS version" -o macos -f true -b binary_folder -e dmg
# Don't overwrite the entire app cast file
netsparkle-generate-appcast --reparse-existing
# Don't overwrite the entire app cast file, but do overwrite items that are still on disk
netsparkle-generate-appcast --reparse-existing --overwrite-old-items
主要版本间升级
有关主要版本间的重大变更和修复信息,请参阅 UPGRADING.md 文件。
常见问题
是否必须将 UI 与 NetSparkleUpdater 一起使用?
不是的。您可以仅引用核心库并自行处理所有事项,包括任何自定义 UI。查看代码示例,了解如何实现这一点!
能否在主 UI 线程以外的其他线程上运行 UI?
这不是内置功能,因为 NetSparkleUpdater 假定它可以安全地在启动 SparkleUpdater 实例的线程上对 UI 进行调用/触发事件。但是,如果您希望这样做,我们提供了一个示例:NetSparkle.Samples.Forms.Multithread。基本上,您无需向 SparkleUpdater 传递 UIFactory,而是自行处理 SparkleUpdater 的事件,并以您希望的任何方式显示 UI - 是的,您仍然可以为此使用内置的 UI 对象!
(请注意,在 Avalonia 上,答案始终为“否”,因为目前它们仅支持一个 UI 线程。)
在 WinForms 上,能否让用户关闭主窗口,同时仍保留更新程序窗体?
可以。您需要在新线程上启动 NetSparkleUpdater 窗体。有关如何通过自行处理事件并仍使用内置 WinForms UIFactory 来实现此目的,请参见 NetSparkle.Samples.Forms.Multithread 示例。
如何使我的 .NET Framework WinForms 应用程序支持高 DPI?
有关使示例应用程序正常工作的修复方法,请参见 #238 和此文档。基本上,您需要使用应用程序配置文件和清单文件,让 Windows 知道您的应用程序是 DPI 感知的。如果这对您不起作用,请尝试 此 SO 帖子 中的一些提示。
同一操作系统上的不同架构怎么办?NetSparkle 支持吗?
支持!
- 从应用程序广播 CLI 工具的 v2.8.1 版本开始(请注意,此工具的版本号与主库不同!),应用程序广播生成器在检查版本是否已存在于应用程序广播中时,会同时检查操作系统和版本
- 请注意,目前应用程序广播生成器不会自动识别应用程序的架构,因此您需要通过
--os命令行参数指定完整的操作系统和架构字符串。
- 请注意,目前应用程序广播生成器不会自动识别应用程序的架构,因此您需要通过
- 从主库的 v3.0 版本开始,应用程序广播中的操作系统字符串可以是
macos-arm64或windows-x64等,而不仅仅是macos或windows - 回滚示例 对您会非常有帮助。它包含了如何查看运行中应用程序的当前架构,以确定哪些项目应向用户提供、过滤掉不适用于当前架构的项目等示例。
关于剪裁,这都是什么?
剪裁 是在应用程序自发布和/或构建为自包含应用程序时减小其文件大小的好方法。简而言之,剪裁会从应用程序(包括外部库)中移除未使用的代码,因此您可以以更小的文件大小发布应用程序。要在发布时剪裁应用程序,请在 csproj 文件中添加 <PublishTrimmed>true</PublishTrimmed>。如果您想剪裁所有程序集(包括那些可能未指定兼容剪裁的程序集),请在 csproj 文件中添加 <TrimMode>full</TrimMode>;要仅剪裁那些已选择加入的程序集,请使用 <TrimMode>partial</TrimMode>。要启用剪裁警告,请添加 <SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>。
还有其他可用选项,您可以在 Microsoft 的文档 此处 了解更多信息。对于那些可能无法使用内置剪裁选项的应用程序,请尝试 Zack.DotNetTrimmer 或您可能找到的其他解决方案。
我们建议您在发布应用程序并分发给用户之前对其进行剪裁。NetSparkle 的一些默认依赖项相当大,但通过剪裁过程可以大幅减小文件大小。如果您选择剪裁应用程序,不要忘记在剪裁后对其进行测试,并确保修复出现的任何警告!
您还可以在 此处 阅读有关剪裁库的更多信息。
此库是否兼容 AOT 编译?
是的。
此库是否支持可为空引用类型?
是的。
我可以为应用广播项的下载链接使用相对路径吗?
可以。在应用广播生成器中,您可以使用类似 -u ../ 的命令,使 NetSparkle 在服务器的 appcast.xml 文件所在目录的上级目录中查找下载文件。
我在 NuGet 上搜索“NetSparkle”时会出现很多包,应该使用哪个?
如果您需要不带内置 UI 的库,NetSparkleUpdater.SparkleUpdater 是正确的选择。否则,请使用 NetSparkleUpdater.UI.{YourChoiceOfUI},它将为您提供内置 UI 和核心库。2.0 版本之前,UI 库引用 NetSparkle.New,该包现已弃用。
以下是已弃用包的完整列表:
com.pikleproductions.netsparkle-- 由NetSparkleUpdater.SparkleUpdater替代com.pikleproductions.netsparkle.tools-- 由NetSparkleUpdater.Tools.AppCastGenerator和NetSparkleUpdater.Tools.DSAHelper替代NetSparkle.New-- 由NetSparkleUpdater.SparkleUpdater替代NetSparkle.New.Tools-- 由NetSparkleUpdater.Tools.AppCastGenerator和NetSparkleUpdater.Tools.DSAHelper替代NetSparkleUpdater.Tools-- 由NetSparkleUpdater.Tools.AppCastGenerator和NetSparkleUpdater.Tools.DSAHelper替代
我必须将所有发布版本都放入单个应用广播文件中吗?
不必。如果您的应用仅使用 NetSparkle 来判断是否有更新版本,并且不以任何方式将应用广播用作引用应用历史版本的途径,那么无需将所有已发布版本添加到应用广播文件中。
仅在应用广播中保留软件的最新版本还有一个额外好处:您无需为应用广播生成工具提供所有版本的二进制文件和更新日志。例如,这可能会使通过 GitHub Actions 进行自动发布构建变得更加容易——因为所需的唯一数据是从您的 git 仓库生成的 .exe 文件和更新日志。
如何将 NetSparkleUpdater 与 AppCenter 配合使用?
注意:AppCenter 计划于 2025 年 3 月 31 日停止服务。
- 确保您已阅读 此处 的文档
- 决定是否要为文件生成签名。如果需要,请确保签名功能正常工作,然后正常使用 NetSparkleUpdater。
- 如果由于信任 AppCenter 构建而不想生成签名,请使用
SecurityMode.Unsafe或以下IAppCastHandler重写:
public override bool DownloadAndParse()
{
try
{
_logWriter.PrintMessage("Downloading app cast data...");
var appCast = _dataDownloader.DownloadAndGetAppCastData(_castUrl);
if (!string.IsNullOrWhiteSpace(appCast))
{
Items.Clear();
Items.AddRange(ParseAppCast(appcast));
return true;
}
}
catch (Exception e)
{
_logWriter.PrintMessage("Error reading app cast {0}: {1} ", _castUrl, e.Message);
}
return false;
}
应用程序版本是否支持回滚?
答案是既支持也不支持。不支持,是因为这不是默认行为。支持,是因为如果您为每个版本都使用安装程序,则可以使用应用程序广播(app cast)查看可用的历史版本并下载这些版本。如果您的安装程序是独立的,它们应该可以正常安装旧版本。但请记住,如果您安装了旧版本,而应用程序广播中又存在更新的版本,那么在打开旧版软件后,它会询问用户是否要更新到新版本!
以下是您可以执行的操作摘要:
- 设置您的
SparkleUpdater对象 - 调用
_updateInfo = await _sparkle.CheckForUpdatesQuietly();(不显示 UI)或_sparkle.CheckForUpdatesAtUserRequest()(显示 UI)。建议使用静默检查,因为 UI 方法始终会显示最新版本。您也可以自行显示自定义 UI。 - 在
_updateInfo.Updates中查看应用程序广播中的可用版本。您可以将其与当前安装的版本进行比较,以确定哪些是新版本,哪些是旧版本。 - 使用要下载的更新调用
await _sparkle.InitAndBeginDownload(update);。下载路径会在DownloadFinished事件中提供。 - 下载完成后,调用
_sparkle.InstallUpdate(update, _downloadPath);
自行处理事件示例 和 回滚示例 将对您学习如何执行此类操作非常有帮助。
我想在应用程序广播(app cast)中添加自定义属性。我可以自己处理应用程序广播文件的序列化/反序列化吗?
可以。实现 IAppCastGenerator 并将 SparkleUpdater.AppCastGenerator 属性设置为您的类的实例。您需要实现以下方法:
AppCast DeserializeAppCast(string appCastString);
Task<AppCast> DeserializeAppCastAsync(string appCastString);
AppCast DeserializeAppCastFromFile(string filePath);
Task<AppCast> DeserializeAppCastFromFileAsync(string filePath);
string SerializeAppCast(AppCast appCast);
Task<string> SerializeAppCastAsync(AppCast appCast);
void SerializeAppCastToFile(AppCast appCast, string outputPath);
Task SerializeAppCastToFileAsync(AppCast appCast, string outputPath);
如您所见,许多这些函数都是您想要完成的核心序列化和反序列化过程的微小变体。您可以查看 JsonAppCastGenerator 和 XMLAppCastGenerator 的实现作为示例。
我可以使用 XML 或 JSON 以外的应用程序广播格式吗?
可以。实现 IAppCastGenerator 并将 SparkleUpdater.AppCastGenerator 属性设置为您的类的实例。不过,您需要自己制作实际的应用程序广播文件,因为应用程序广播生成器目前仅与 XML 和 JSON 兼容。
这是否适用于 Avalonia XYZ 版本?
目前,我们兼容版本 11。如果您需要进行更改,可以使用自己的 IUIFactory 实现来解决出现的任何问题。
我还能使用 DSA 签名吗?
在使用 NetSparkleUpdater 2.0+ 时,不建议使用 DSA 签名。它们被认为是不安全的!
不过,您仍然可以使用 DSAHelper 工具(来自此 NuGet 包或此处的源代码)生成/使用这些签名。密钥生成仅在 Windows 上有效,因为 .NET Core 3 在 macOS/Linux 上没有生成 DSA 密钥的适当实现;但是,您可以在任何平台上获取文件的 DSA 签名。如果需要生成 DSA 公钥/私钥,请在 Windows 上像这样使用 DSAHelper 工具:
netsparkle-dsa /genkey_pair
你可以像这样使用 DSAHelper 来获取签名:
netsparkle-dsa /sign_update {YourInstallerPackage.msi} {NetSparkle_PrivateKey_DSA.priv}
安装 DSA 辅助命令行工具
dotnet tool install --global NetSparkleUpdater.Tools.DSAHelper- 现在,你可以在命令行中使用
netsparkle-dsa命令来调用该工具
DSA 代码
在 SparkleUpdater 构造函数中传入 DSAChecker,而非 Ed25519Checker。
如何从 DSA 签名过渡到 ed25519 签名?
如果你的应用使用 DSA 签名,从预览版 2.0.0-20200607001 开始,应用 cast 生成器默认使用 Ed25519 签名。要过渡到 Ed25519 签名,请创建一个更新,其中软件包含新的 Ed25519 公钥以及一个使用 Ed25519 签名的新应用 cast 的新 URL。上传此更新时,其应用 cast 需使用 DSA 签名,以便旧的支持 DSA 的应用能够下载支持 Ed25519 的更新。之后,所有未来的更新和应用 cast 都应使用 Ed25519。
遇到问题?寻求帮助!
以下是一些可帮助你排查应用运行问题的方法:
- 确保已启用应用调试并进行了全面调试。一种有效的方法是设置
SparkleUpdater.LogWriter = new LogWriter(LogWriterOutputMode.Console),然后在调试时观察控制台输出。 - 下载本仓库并运行示例,查看 NetSparkleUpdater 示例。你甚至可以尝试在示例中放入你的应用 cast URL,并使用你的公钥结合源代码进行调试!
- 在我们的 Gitter 上寻求帮助
- 发布 issue,等待他人提供协助
是否接受贡献?
是的!请帮助我们让这个库变得更出色!
此处的标签方案是什么?
- Major.Minor.Patch(核心)
- Major.Minor.Patch-app-cast-generator
- Major.Minor.Patch-dsa-helper
- Major.Minor.Patch-UI-Avalonia
- Major.Minor.Patch-UI-WinForms
- Major.Minor.Patch-UI-WPF
要求
- .NET Framework 4.6.2+ | .NET 6+
许可证
NetSparkle 基于 MIT 许可证 提供。
贡献
始终欢迎贡献!如果你想添加新功能,请先打开 issue 进行讨论,然后再提交实现该功能的 PR。如果你发现了 bug,请提交包含修复的 PR 或创建 issue!非常感谢! 😃 你也可以加入我们的 Gitter 聊天室!
请注意,在任何情况下都不会接受 AI 生成的代码。谢谢。
我们需要帮助/贡献的领域
- 项目所有部分的单元测试,包括UI单元测试、完整下载测试等。
- 在macOS/Linux上进行广泛的测试/升级
- 应用程序更新信息生成器中增加更多选项
- 更多内容请参见问题列表
致谢
- 最初的NetSparkle库,可在dei79/netsparkle找到
- 一个用于查找基本目录的函数取自MIT许可的WalletWasabi
- MarkdownSharp来自此处
- 我们的初始README布局借鉴自MahApps.Metro,这是一个出色的WPF UI框架
其他选项
如果NetSparkleUpdater不适合您,以下是一些与软件更新相关的其他项目的不完整列表,您可能需要查看:
Introduction
NetSparkle is a C#, cross-platform, highly-configurable software update framework with pre-built UI for .NET developers compatible with .NET 4.6.2/.NET 6+, WinForms, WPF, and Avalonia; uses Ed25519 signatures. View basic usage here in the README and try the samples for yourself.