
UpSparkle
Thin .NET wrapper around WinSparkle (Windows) and Sparkle (macOS). One NuGet package, two platforms.
About
UpSparkle gives .NET desktop apps a cross-platform auto-update UI without any platform-specific plumbing code. It ships a single netstandard2.0 NuGet package that automatically picks the right native binary at runtime.
- Windows — wraps WinSparkle
- macOS / Mac Catalyst — wraps Sparkle
Quickstart
1. Install the NuGet package
dotnet add package UpSparkleOr via Package Manager Console in Visual Studio:
Install-Package UpSparkle2. Configure your project
Initialize reads your app’s metadata from the executing assembly, so you need to set those values in your project first.
Windows — SDK-style project (.csproj)
Add company, product, and version to your <PropertyGroup>, then declare the UpSparkle-specific metadata in an <ItemGroup>:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Company>Wayne Enterprise</Company>
<Product>BatComputer App</Product>
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<!-- Required: URL of your appcast XML feed -->
<AssemblyMetadata Include="SUFeedURL" Value="https://example.com/appcast.xml" />
<!-- Required: Base64-encoded EdDSA public key for verifying update signatures -->
<AssemblyMetadata Include="SUPublicEDKey" Value="<your-base64-eddsa-public-key>" />
</ItemGroup>
</Project>These map to AssemblyCompanyAttribute, AssemblyProductAttribute, AssemblyInformationalVersionAttribute, and AssemblyMetadataAttribute respectively — all of which Initialize reads at runtime.
Windows — classic .NET Framework project (AssemblyInfo.cs)
For non-SDK-style projects (e.g. .NET Framework 4.6.2 targeting net462 without <Project Sdk="...">), the <ItemGroup>/<AssemblyMetadata> shorthand is not available. Add the attributes directly to your Properties\AssemblyInfo.cs instead:
using System.Reflection;
// Standard assembly identity attributes
[assembly: AssemblyCompany("Wayne Enterprise")]
[assembly: AssemblyProduct("BatComputer App")]
[assembly: AssemblyInformationalVersion("1.0.0")]
// UpSparkle-specific metadata
[assembly: AssemblyMetadata("SUFeedURL", "https://example.com/appcast.xml")]
[assembly: AssemblyMetadata("SUPublicEDKey", "<your-base64-eddsa-public-key>")]
AssemblyMetadatais inSystem.Reflectionand is available in .NET Framework 4.5+.
macOS — Info.plist
On macOS, Sparkle reads its configuration directly from the app bundle’s Info.plist. At minimum you need:
<!-- Required: where Sparkle checks for updates -->
<key>SUFeedURL</key>
<string>https://example.com/appcast.xml</string>
<!-- Required: EdDSA public key for verifying update signatures -->
<key>SUPublicEDKey</key>
<string><your-base64-eddsa-public-key></string>Commonly used optional keys:
<!-- Skip the automatic-check permission prompt on second launch -->
<key>SUEnableAutomaticChecks</key>
<true/>
<!-- How often to poll for updates, in seconds (default: 86400 = 1 day) -->
<key>SUScheduledCheckInterval</key>
<integer>86400</integer>
<!-- Silently download and install in the background -->
<key>SUAutomaticallyUpdate</key>
<false/>
<!-- Show release notes in the update alert -->
<key>SUShowReleaseNotes</key>
<true/>For the full list of supported keys see the Sparkle customization docs.
To generate your EdDSA key pair, use the generate_keys tool that ships with Sparkle. See the EdDSA signatures guide for step-by-step instructions.
3. Initialize the updater
Create one UpSparkleUpdater instance per application (typically at startup) and call Initialize. The simplest form reads everything from the executing assembly:
using UpSparkle;
var updater = new UpSparkleUpdater();
// Reads SUFeedURL and SUPublicEDKey from AssemblyMetadata,
// and company/product/version from standard assembly attributes.
updater.Initialize(System.Reflection.Assembly.GetExecutingAssembly());You can also pass the appcast URL and/or public key directly — they take precedence over the assembly metadata:
updater.Initialize(
assemblyInfo: System.Reflection.Assembly.GetExecutingAssembly(),
appcastUrl: "https://example.com/appcast.xml",
edDSAPublicKey: "<your-base64-eddsa-public-key>");After a successful call, the following properties are available:
| Property | Description |
|---|---|
IsInitialized | true once Initialize has succeeded |
AppcastUrl | The resolved appcast feed URL |
EdDSAPublicKey | The resolved EdDSA public key |
CompanyName | Resolved from AssemblyCompanyAttribute |
AppName | Resolved from AssemblyProductAttribute |
AppVersion | Resolved from AssemblyInformationalVersionAttribute (build metadata suffix stripped) |
4. Check for updates
Call CheckUpdateWithUI() to open the native update dialog — wire this to a menu item, toolbar button, or call it automatically on startup:
updater.CheckUpdateWithUI();
CheckUpdateWithUIthrowsInvalidOperationExceptionif called beforeInitialize.
5. Clean up on exit
Dispose the updater when the application closes to release native resources:
updater.Dispose();After disposal, IsInitialized is reset to false.
Full Examples
WPF
using System.Windows;
using UpSparkle;
public partial class MainWindow : Window
{
private readonly UpSparkleUpdater _updater = new UpSparkleUpdater();
private void Window_Loaded(object sender, RoutedEventArgs e)
{
_updater.Initialize(System.Reflection.Assembly.GetExecutingAssembly());
}
private void CheckForUpdates_Click(object sender, RoutedEventArgs e)
{
_updater.CheckUpdateWithUI();
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
_updater.Dispose();
}
}WinForms
using System.Windows.Forms;
using UpSparkle;
public partial class Form1 : Form
{
private readonly UpSparkleUpdater _updater = new UpSparkleUpdater();
private void Form1_Load(object sender, EventArgs e)
{
_updater.Initialize(System.Reflection.Assembly.GetExecutingAssembly());
}
private void btnCheckUpdate_Click(object sender, EventArgs e)
{
_updater.CheckUpdateWithUI();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
_updater.Dispose();
}
}Avalonia (MVVM)
using System.Reflection;
using UpSparkle;
public partial class MainWindowViewModel : ViewModelBase
{
private readonly UpSparkleUpdater _updater = new UpSparkleUpdater();
public void Init()
{
_updater.Initialize(Assembly.GetExecutingAssembly());
// Properties are populated after Initialize
Console.WriteLine(_updater.CompanyName);
Console.WriteLine(_updater.AppName);
Console.WriteLine(_updater.AppVersion);
}
public void CheckForUpdates()
{
_updater.CheckUpdateWithUI();
}
}MAUI
using System.Reflection;
using UpSparkle;
public partial class MainPage : ContentPage
{
private readonly UpSparkleUpdater _updater = new UpSparkleUpdater();
public MainPage()
{
InitializeComponent();
this.Loaded += (_, _) =>
_updater.Initialize(Assembly.GetExecutingAssembly());
this.Disappearing += (_, _) =>
_updater.Dispose();
}
private void OnCheckUpdatesClicked(object sender, EventArgs e)
{
_updater.CheckUpdateWithUI();
}
}API Reference
UpSparkleUpdater
public class UpSparkleUpdater : IDisposableConstructor
new UpSparkleUpdater()Creates a new updater instance. The native backend is not started until Initialize is called.
Methods
void Initialize(Assembly assemblyInfo, string appcastUrl = null, string edDSAPublicKey = null)Starts the native Sparkle / WinSparkle framework. Reads company name, app name, and version from the assembly’s standard attributes. appcastUrl and edDSAPublicKey are resolved from parameters first, then from AssemblyMetadata entries with keys "SUFeedURL" and "SUPublicEDKey" respectively.
Throws ArgumentNullException if assemblyInfo is null. Throws ArgumentException if a required value cannot be resolved.
void CheckUpdateWithUI()Opens the native update UI. Throws InvalidOperationException if called before Initialize.
void Dispose()Shuts down the native updater and releases native resources. Resets IsInitialized to false.
Properties
bool IsInitialized { get; }
string AppcastUrl { get; }
string EdDSAPublicKey { get; }
string CompanyName { get; }
string AppName { get; }
string AppVersion { get; }All properties return null before Initialize is called.
Constants
const string SUFeedURL = nameof(SUFeedURL);
const string SUPublicEDKey = nameof(SUPublicEDKey);Keys used to look up AssemblyMetadata values from the assembly. Match the corresponding Info.plist keys on macOS. These live in the internal UpSparkle.UpSparkleSettings class.
Supported Platforms
| Platform | Minimum version |
|---|---|
| Windows (x86 / x64 / Arm64) | .NET Framework 4.6.2, or .NET 6+ |
| macOS (Apple Silicon / Intel) | .NET 6+ |
| Mac Catalyst (Apple Silicon / Intel) | .NET 6+ |
Tested project types:
Windows — WinForms, WPF, WinUI, Avalonia UI, MAUI (WinUI)
macOS — .NET macOS, MAUI (Mac Catalyst), Avalonia UI, Uno Platform
Appcast & Signing
UpSparkle requires an appcast XML feed hosted at a public URL. Every update package must be signed with an EdDSA key pair.
Generate your keys with the generate_keys tool that ships with Sparkle, then follow the EdDSA signatures guide to sign your releases.
Development
Before starting development, fetch the native dependencies by running the script for your platform.
macOS / Linux
./getlibs.shWindows (PowerShell)
.\Get-Libraries.ps1Both scripts download and extract binaries based on .gitbinmodules into the libs directory. To use a different version of Sparkle or WinSparkle, edit .gitbinmodules and re-run the script.
Credits
- sparkle-project/Sparkle — macOS native framework
- vslavik/winsparkle — Windows native implementation