프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

markus / MarkusAutoUpdate / README.md @ master

이력 | 보기 | 이력해설 | 다운로드 (42.4 KB)

1
# NetSparkle
2

    
3
 [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/NetSparkleUpdater/NetSparkle?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) [![Issues](https://img.shields.io/github/issues/NetSparkleUpdater/NetSparkle.svg?style=flat-square)](https://github.com/NetSparkleUpdater/NetSparkle/issues)
4

    
5
NetSparkle is a software update framework for C# that is compatible with .NET Core 3+ and .NET Framework 4.5.2+, has pre-built UIs for .NET Framework (WinForms, WPF) and .NET Core (WinForms, WPF, Avalonia), uses Ed25519 or other signatures, and even allows for custom UIs or no UI at all! You provide, somewhere on the internet, an [app cast](#app-cast) with update and version information, along with release notes in Markdown or HTML format. This library then helps you check for an update, show the user the release notes, and offer to download/install the new version of the software. 
6

    
7
The `develop` branch has changed significantly from `master` and represents a major 2.0 version update. NetSparkle 2.0, currently in beta, brings the ability to customize most of NetSparkle -- custom UIs are easy, you can have custom app cast downloaders and handlers (e.g. for FTP download or JSON appcasts), and more! No more big changes to the API are planned (but we cannot guarantee it before 2.0 RC), but smaller API changes may occur if bugs are found between now and the official 2.0 release.
8

    
9
Built-in supported update download types:
10
* Windows -- .exe, .msi, .msp
11
* macOS -- .zip, .pkg, .dmg
12
* Linux -- .tar.gz, .deb, .rpm
13

    
14
_README and other documentation updates for version 2.0 are in progress. If you have specific questions or need help even after looking at the samples, please file an issue or message me on [Gitter](https://gitter.im/NetSparkleUpdater/NetSparkle). You should be able to implement your own handlers and/or UI for most operations, so things like a custom update process, downloading/parsing JSON rather than XML, downloading things from FTP, using your own file signature verification method, etc. are all now possible. Some extra features aren't built-in out of the box yet, such as JSON app cast feeds -- contributions are welcome and benefit the whole community!_
15

    
16
## Contributing
17

    
18
Contributions are ALWAYS welcome! If you see a new feature you'd like to add, please open an issue to talk about it first, then open a PR for that implementation. If there's a bug you find, please open a PR with the fix or file an issue! Thank you!! :) You can also join us in our [Gitter chat room](https://gitter.im/NetSparkleUpdater/NetSparkle)!
19

    
20
## Installing NetSparkle
21

    
22
NetSparkle is available via NuGet. To choose a NuGet package to use:
23

    
24
* Reference the core NetSparkle build if you don't care about having a built-in UI and can manage things yourself
25
* Choose one of the other packages if you want a built-in UI or want to create your UI based on one of the other UIs
26

    
27
| Package | Use Case | Release | Preview | Downloads |
28
| ------- | -------- | ------- | ------- | --------- |
29
| NetSparkle | Core package; No UI or 100% custom UI | [![NuGet](https://img.shields.io/nuget/v/NetSparkle.New.svg?style=flat-square)](https://www.nuget.org/packages/NetSparkle.New/) | [![NuGet](https://img.shields.io/nuget/vpre/NetSparkle.New.svg?style=flat-square&label=nuget-pre)](https://www.nuget.org/packages/NetSparkle.New/) | [![NuGet](https://img.shields.io/nuget/dt/NetSparkle.New.svg?style=flat-square)](https://www.nuget.org/packages/NetSparkle.New/) |
30
| WinForms UI (.NET Framework) | NetSparkle with built-in WinForms UI | [![NuGet](https://img.shields.io/nuget/v/NetSparkleUpdater.UI.WinForms.NetFramework.svg?style=flat-square)](https://www.nuget.org/packages/NetSparkleUpdater.UI.WinForms.NetFramework/) | [![NuGet](https://img.shields.io/nuget/vpre/NetSparkleUpdater.UI.WinForms.NetFramework.svg?style=flat-square&label=nuget-pre)](https://www.nuget.org/packages/NetSparkleUpdater.UI.WinForms.NetFramework/) | [![NuGet](https://img.shields.io/nuget/dt/NetSparkleUpdater.UI.WinForms.NetFramework.svg?style=flat-square)](https://www.nuget.org/packages/NetSparkleUpdater.UI.WinForms.NetFramework/) |
31
| WinForms UI (.NET Core) | NetSparkle with built-in WinForms UI | [![NuGet](https://img.shields.io/nuget/v/NetSparkleUpdater.UI.WinForms.NetCore.svg?style=flat-square)](https://www.nuget.org/packages/NetSparkleUpdater.UI.WinForms.NetCore/) | [![NuGet](https://img.shields.io/nuget/vpre/NetSparkleUpdater.UI.WinForms.NetCore.svg?style=flat-square&label=nuget-pre)](https://www.nuget.org/packages/NetSparkleUpdater.UI.WinForms.NetCore/) | [![NuGet](https://img.shields.io/nuget/dt/NetSparkleUpdater.UI.WinForms.NetCore.svg?style=flat-square)](https://www.nuget.org/packages/NetSparkleUpdater.UI.WinForms.NetCore/) |
32
| WPF UI (.NET Framework and Core) | NetSparkle with built-in WPF UI | [![NuGet](https://img.shields.io/nuget/v/NetSparkleUpdater.UI.WPF.svg?style=flat-square)](https://www.nuget.org/packages/NetSparkleUpdater.UI.WPF/) | [![NuGet](https://img.shields.io/nuget/vpre/NetSparkleUpdater.UI.WPF.svg?style=flat-square&label=nuget-pre)](https://www.nuget.org/packages/NetSparkleUpdater.UI.WPF/) | [![NuGet](https://img.shields.io/nuget/dt/NetSparkleUpdater.UI.WPF.svg?style=flat-square)](https://www.nuget.org/packages/NetSparkleUpdater.UI.WPF/) |
33
| [Avalonia](https://github.com/AvaloniaUI/Avalonia) UI | NetSparkle with built-in Avalonia UI | [![NuGet](https://img.shields.io/nuget/v/NetSparkleUpdater.UI.Avalonia.svg?style=flat-square)](https://www.nuget.org/packages/NetSparkleUpdater.UI.Avalonia/) | [![NuGet](https://img.shields.io/nuget/vpre/NetSparkleUpdater.UI.Avalonia.svg?style=flat-square&label=nuget-pre)](https://www.nuget.org/packages/NetSparkleUpdater.UI.Avalonia/) | [![NuGet](https://img.shields.io/nuget/dt/NetSparkleUpdater.UI.Avalonia.svg?style=flat-square)](https://www.nuget.org/packages/NetSparkleUpdater.UI.Avalonia/) |
34
| Command Line Tools | DSA helper; AppCast generator (incl. Ed25519 helpers) | [![NuGet](https://img.shields.io/nuget/v/NetSparkleUpdater.Tools.svg?style=flat-square)](https://www.nuget.org/packages/NetSparkleUpdater.Tools/) | [![NuGet](https://img.shields.io/nuget/vpre/NetSparkleUpdater.Tools.svg?style=flat-square&label=nuget-pre)](https://www.nuget.org/packages/NetSparkleUpdater.Tools/) | [![NuGet](https://img.shields.io/nuget/dt/NetSparkleUpdater.Tools.svg?style=flat-square)](https://www.nuget.org/packages/NetSparkleUpdater.Tools/) |
35

    
36
All notable changes to this project will be documented in the [changelog](CHANGELOG.md).
37

    
38
- [How Updates Work](#how-updates-work)
39
- [Basic Usage](#basic-usage)
40
- [Appcast](#app-cast)
41
- [Updating from 0.x or 1.x](#updating-from-0x-or-1x)
42
- SparkleUpdater class
43
    - [Public Methods](#public-methods)
44
    - [Public Properties](#public-properties)
45
    - [Public Events](#public-events)
46
- [License](#license)
47
- [Requirements](#requirements)
48
- [Other Options](#other-options)
49

    
50
## How updates work
51

    
52
A typical software update path for a stereotypical piece of software might look like this:
53

    
54
1. Compile application so it can be run on other computers (e.g. `dotnet publish`)
55
2. Programmer puts app in some sort of installer/zip/etc. for distribution (e.g. InnoSetup for Windows)
56
3. Programmer creates app cast file (see the [appcast](#appcast) section of this document for more info on how to create this)
57
4. Programmer uploads files for distribution (installer, app cast file, appcast-file.signature file) to their download site.
58
5. Client opens app and is automatically notified of an available update (or the software otherwise detects there is an update)
59
6. Client chooses to update (or update is downloaded if the software downloads it automatically)
60
7. Update is downloaded and sitting on the user's disk
61
8. User is asked to close the software so the update can run. User closes the software.
62
9. Downloaded file/installer is run (or the update is otherwise performed)
63

    
64
Right now, NetSparkle **does not** help you with 1., 2., or 4. "Why not?", you might ask:
65

    
66
* 1. We can't compile your application for you since we don't know (or care) how you are compiling or packaging your application! :)
67
* 2. A cross-platform installer package/system would be difficult and may not feel normal to end users, although a system that uses [Avalonia](https://github.com/AvaloniaUI/Avalonia) could maybe work I suppose (might take a lot of work though and make downloads large!). We do not provide support for getting your installer/distribution ready. To generate your installer/distribution, we recommend the following:
68
  * Windows: [InnoSetup](https://jrsoftware.org/isinfo.php) or [NSIS](https://nsis.sourceforge.io/Main_Page) or [WiX](https://wixtoolset.org/)
69
  * macOS: If you have a .app to distribute, use [dotnet-bundle](https://github.com/egramtel/dotnet-bundle) with [create-dmg](https://github.com/sindresorhus/create-dmg). If you want an installer, create a .pkg installer with [macos-installer-builder](https://github.com/KosalaHerath/macos-installer-builder) (tutorial [here](https://medium.com/swlh/the-easiest-way-to-build-macos-installer-for-your-application-34a11dd08744)), [Packages](http://s.sudre.free.fr/Software/Packages/about.html), or [your terminal](https://www.techrepublic.com/article/pro-tip-use-terminal-to-create-packages-for-software-deployment/). Otherwise, plop things in a zip file.
70
  * Linux: Use [dotnet-packaging](https://github.com/qmfrederik/dotnet-packaging/) to create an rpm, deb, or tar.gz file for your users.
71
* 4. We don't know where your files will live on the internet, so you need to be responsible for uploading these files and putting them online somewhere.
72

    
73
To create your app cast file, see the [appcast](#appcast) section of this document.
74

    
75
We are open to contributions that might make the overall install/update process easier for the user. Please file an issue first with your idea before starting work so we can talk about it.
76

    
77
## Basic Usage
78

    
79
**Please look at the sample projects in this repository for basic, runnable usage samples!!** There are samples on using each of the built-in UIs as well as a "do it yourself in your own UI" sample!
80

    
81
```csharp
82
_sparkle = new SparkleUpdater(
83
    "http://example.com/appcast.xml", // link to your app cast file
84
    new Ed25519Checker(SecurityMode.Strict, // security mode -- use .Unsafe to ignore all signature checking (NOT recommended or secure!!)
85
                       "base_64_public_key") // your base 64 public key -- generate this with the NetSparkleUpdater.Tools AppCastGenerator on any OS
86
) {
87
    UIFactory = new NetSparkleUpdater.UI.WPF.UIFactory(icon) // or null or choose some other UI factory or build your own!
88
};
89
_sparkle.StartLoop(true); // `true` to run an initial check online -- only call StartLoop once for a given SparkleUpdater instance!
90
```
91

    
92
On the first Application.Idle event, your App Cast XML file will be downloaded, read, and compared to the currently running version. If it has a software update inside, the user will be notified with a little toast notification (if supported by the UI and enabled) or with an update dialog containing your release notes. The user can then ignore the update, ask to be reminded later, or download/install it now.
93

    
94
If you want to check for an update in the background without the user seeing anything, use
95

    
96
```csharp
97
_sparkle.CheckForUpdatesQuietly();
98
```
99

    
100
If you want to have a menu item for the user to check for updates so the user can see the UI while NetSparkle looks for updates, use
101

    
102
```csharp
103
_sparkle.CheckForUpdatesAtUserRequest();
104
```
105

    
106
If you have files that need saving, subscribe to the PreparingToExit event:
107

    
108
```csharp
109
_sparkle.PreparingToExit += ((x, cancellable) =>
110
{
111
	// ask the user to save, whatever else is needed to close down gracefully
112
});
113
```
114

    
115
Note that if you do _not_ use a `UIFactory`, you **must** use the `CloseApplication` or `CloseApplicationAsync` events to close your application; otherwise, your downloaded update file will never be executed/read! The only exception to this is if you want to handle all aspects of installing the update package yourself.
116

    
117
The file that launches your downloaded update executable only waits for 90 seconds before giving up! Make sure that your software closes within 90 seconds of [CloseApplication](#closeapplication)/[CloseApplicationAsync](#closeapplicationasync) being called if you implement those events! If you need an event that can be canceled, such as when the user needs to be asked if it's OK to close (e.g. to save their work), use [AboutToExitForInstallerRun](#abouttoexitforinstallerrun)/[AboutToExitForInstallerRunAsync](#abouttoexitforinstallerrunasync).
118

    
119
## App Cast
120

    
121
NetSparkle uses [Sparkle](https://github.com/sparkle-project/Sparkle)-compatible app casts _for the most part_. NetSparkle uses `sparkle:signature` rather than `sparkle:dsaSignature` so that you can choose how to sign your files/app cast. NetSparkle is compatible with and uses Ed25519 signatures by default, but the framework can handle a different implementation of the `ISignatureVerifier` class to check different kinds of signatures without a major version bump/update.
122

    
123
_Note: if your app has DSA signatures, the app cast generator uses Ed25519 signatures by default starting with preview 2.0.0-20200607001. To transition to Ed25519 signatures, create an update where the software has your new Ed25519 public key and a NEW url for a NEW app cast that uses Ed25519 signatures. Upload this update with an app cast that has DSA signatures so your old DSA-enabled app can download the Ed25519-enabled update. Then, future updates and app casts should all use Ed25519._
124

    
125
Here is a sample app cast:
126

    
127
```xml
128
<?xml version="1.0" encoding="UTF-8"?>
129
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
130
    <channel>
131
        <title>NetSparkle Test App</title>
132
        <link>https://netsparkleupdater.github.io/NetSparkle/files/sample-app/appcast.xml</link>
133
        <description>Most recent changes with links to updates.</description>
134
        <language>en</language>
135
        <item>
136
            <title>Version 2.0 (2 bugs fixed; 3 new features)</title>
137
            <sparkle:releaseNotesLink>
138
            https://netsparkleupdater.github.io/NetSparkle/files/sample-app/2.0-release-notes.md
139
            </sparkle:releaseNotesLink>
140
            <pubDate>Thu, 27 Oct 2016 10:30:00 +0000</pubDate>
141
            <enclosure url="https://netsparkleupdater.github.io/NetSparkle/files/sample-app/NetSparkleUpdate.exe"
142
                       sparkle:version="2.0"
143
                       sparkle:os="windows"
144
                       length="12288"
145
                       type="application/octet-stream"
146
                       sparkle:signature="NSG/eKz9BaTJrRDvKSwYEaOumYpPMtMYRq+vjsNlHqRGku/Ual3EoQ==" />
147
        </item>
148
    </channel>
149
</rss>
150
```
151

    
152
NetSparkle reads the `<item>` tags to determine whether updates are available.
153

    
154
The important tags in each `<item>` are:
155

    
156
- `<description>`
157
    - A description of the update in HTML or Markdown.
158
    - Overrides the `<sparkle:releaseNotesLink>` tag.
159
- `<sparkle:releaseNotesLink>`
160
    - The URL to an HTML or Markdown document describing the update.
161
    - If the `<description>` tag is present, it will be used instead.
162
    - **Attributes**:
163
        - `sparkle:signature`, optional: the DSA signature of the document; NetSparkle does not check this DSA signature for you unless you set `ReleaseNotesGrabber.ChecksReleaseNotesSignature` to `true`, but you may manually verify changelog DSA signatures if you like or set `ReleaseNotesGrabber.ChecksReleaseNotesSignature = true` in your UI.
164
- `<pubDate>`
165
    - The date this update was published
166
- `<enclosure>`
167
    - This tag describes the update file that NetSparkle will download.
168
    - **Attributes**:
169
        - `url`: URL of the update file
170
        - `sparkle:version`: machine-readable version number of this update
171
        - `length`, optional: (not validated) size of the update file in bytes
172
        - `type`: ignored
173
        - `sparkle:signature`: DSA signature of the update file
174
        - `sparkle:criticalUpdate`, optional: if equal to `true` or `1`, the UI will indicate that this is a critical update
175
        - `sparkle:os`: Operating system for the app cast item. Defaults to Windows if not supplied. For Windows, use "win" or "windows"; for macOS, use "macos" or "osx"; for Linux, use "linux".
176

    
177
By default, you need 2 (DSA) signatures (`SecurityMode.Strict`):
178

    
179
1. One in the enclosure tag for the update file (`sparkle:signature="..."`)
180
2. Another on your web server to secure the actual app cast file. **This file must be located at [AppCastURL].signature**. In other words, if the app cast URL is http://example.com/awesome-software.xml, you need a valid (DSA) signature for that file at http://example.com/awesome-software.xml.signature. 
181

    
182
### Ed25519 Signatures
183

    
184
You can generate Ed25519 signatures using the `AppCastGenerator` tool (from [this NuGet package](https://www.nuget.org/packages/NetSparkleUpdater.Tools/) or in the [source code here](https://github.com/NetSparkleUpdater/NetSparkle/tree/develop/src/NetSparkle.Tools.AppCastGenerator)). **This tool requires the .NET Core 3.1 Desktop Runtime to be installed.** If you need to generate an Ed25519 keypair, use the tool like this:
185

    
186
```bash
187
generate_appcast.exe --generate-keys
188
```
189

    
190
Then you can use the tool like this:
191

    
192
```bash
193
generate_appcast.exe -a directory/for/appcast/ -e exe -b directory/with/binaries/ -o windows
194
```
195

    
196
You can use the `AppCastGenerator` tool to verify your binaries:
197

    
198
```bash
199
generate_appcast.exe --verify path/to/binary.exe --signature base_64_signature
200
```
201

    
202
If you want to make a signature for a binary, you can do so like this:
203

    
204
```bash
205
generate_appcast.exe --generate-signature path/to/binary.exe
206
```
207

    
208
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, you can do:
209

    
210
```bash
211
generate_appcast.exe --export
212
```
213

    
214
Or you can store keys in a custom location:
215

    
216
```bash
217
generate_appcast.exe --key-path path/to/store/keys
218
```
219

    
220
If you want to use keys dynamically, you can set the `SPARKLE_PRIVATE_KEY` and `SPARKLE_PUBLIC_KEY` environment variables before running `generate_appcast`. The tool prioritizes environment keys over keys sitting on disk!
221

    
222
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:
223

    
224
```bash
225
generate_appcast.exe --key-path path/to/keys/
226
```
227

    
228

    
229
### DSA Signatures
230

    
231
DSA signatures are not recommended for 2.0. They are insecure!
232

    
233
You can generate these signatures using the `DSAHelper` tool (from [this NuGet package](https://www.nuget.org/packages/NetSparkleUpdater.Tools/) or in the [source code here](https://github.com/NetSparkleUpdater/NetSparkle/tree/develop/src/NetSparkle.Tools.DSAHelper)). If you need to generate a DSA public/private key, please use the same tool on Windows like this: 
234

    
235
```
236
NetSparkle.DSAHelper.exe /genkey_pair
237
```
238

    
239
This only works on Windows because .NET Core 3 does not have the proper implementation to generate DSA keys on macOS/Linux.
240

    
241
On any platform, you can use the DSAHelper to get a signature like this:
242

    
243
```
244
NetSparkle.DSAHelper.exe /sign_update {YourInstallerPackage.msi} {NetSparkle_PrivateKey_DSA.priv}
245
```
246

    
247
### How can I make the app cast?
248

    
249
* Use the `AppCastGenerator` tool (from [this NuGet package](https://www.nuget.org/packages/NetSparkleUpdater.Tools/) or in the [source code here](https://github.com/NetSparkleUpdater/NetSparkle/tree/develop/src/NetSparkle.Tools.AppCastGenerator)) to easily create your app cast file.
250
* Rig up a script that generates the app cast for you in python or some other language (`string.Format` or similar is a wonderful thing).
251
* Or you can just copy/paste the above example app cast into your own file and tweak the signatures/download info yourself, then generate the (DSA) signature for the app cast file manually! :)
252

    
253
## Updating from 0.X or 1.X
254

    
255
This section is still WIP, but major changes include:
256

    
257
* Minimum .NET requirement is now .NET Framework 4.5.2 instead of 4.5.1
258
* Change of base namespace from `NetSparkle` to `NetSparkleUpdater`
259
* `Sparkle` renamed to `SparkleUpdater` for clarity
260
* `SparkleUpdater` constructors now require an `ISignatureVerifier` in order to "force" you to choose your signature verification method
261
* `SecurityMode` is a new enum that defines which signatures are required and which signatures are not required
262
  * Added `SecurityMode.OnlyVerifySoftwareDownloads` if you want to verify only software download signatures and don't care about verifying your app cast or release notes
263
* UIs are now in different namespaces. If you want to use a UI, you must pass in a `UIFactory` that implements `IUIFactory` and handles showing/handling all user interface elements
264
  * `SparkleUpdater` no longer holds its own `Icon`
265
  * `HideReleaseNotes`, `HideRemindMeLaterButton`, and `HideSkipButton` are all handled by the `UIFactory` objects
266
* Added built-in UIs for [Avalonia](https://github.com/AvaloniaUI/Avalonia) and WPF
267
* Localization capabilities are non-functional and are expected to come back in a later version. See [this issue](https://github.com/NetSparkleUpdater/NetSparkle/issues/92).
268
* Most `SparkleUpdater` elements are now configurable. For example, you can implement `IAppCastHandler` to implement your own app cast parsing and checking.
269
  * `IAppCastDataDownloader` to implement downloading of your app cast file
270
  * `IAppCastHandler` to implement your own app cast parsing
271
  * `ISignatureVerifier` to implement your own download/app cast signature checking. NetSparkle has built-in DSA and Ed25519 signature verifiers.
272
  * `IUIFactory` to implement your own UI
273
  * `ILogger` to implement your own logger class (rather than being forced to subclass `LogWriter`)
274
  * `Configuration` subclasses now take an `IAssemblyAccessor` in their constructor(s) in order to define where assembly information is loaded from
275
* Samples have been updated and improved
276
  * Sample apps for [Avalonia](https://github.com/AvaloniaUI/Avalonia), WinForms, and WPF UIs
277
  * Sample app to demonstrate how to handle events yourself with your own UI
278
* Many delegates, events, and functions have been renamed, removed, and/or tweaked for clarity and better use
279
  * `DownloadEvent` now has the `AppCastItem` that is being downloaded rather than being just the download path
280
  * `AboutToExitForInstallerRun`/`AboutToExitForInstallerRunAsync` has been renamed to `PreparingToExit`/``PreparingToExitAsync`, respectively
281
  * The `UserSkippedVersion` event has been removed. Use `UserRespondedToUpdate` instead.
282
  * The `RemindMeLaterSelected` event has been removed. Use `UserRespondedToUpdate` instead.
283
  * The `FinishedDownloading`/`DownloadedFileReady` events have been removed. Use `DownloadFinished` instead.
284
* By default, the app cast signature file now has a `.signature` extension. The app cast downloader will look for a file with the old `.dsa` signature if data is not available or found in a `appcast.xml.signature` on your server.
285
* `sparkle:dsaSignature` is now `sparkle:signature` instead. If no `sparkle:signature` is found, `sparkle:dsaSignature` will be used (if available). If `sparkle:dsaSignature` is not found, `sparkle:edSignature` will be used (if available). This is to give us as much compatibility with old versions of `NetSparkle` as well as the macOS `Sparkle` library.
286
* By default, the app cast generator tool now uses Ed25519 signatures. If you don't want to use files on disk to store your keys, set the `SPARKLE_PRIVATE_KEY` and `SPARKLE_PUBLIC_KEY` environment variables before running the app cast generator tool. You can also store these signatures in a custom location with the `--key-path` flag.
287
* Removed `AssemblyAccessor` class (in lieu of `IAssemblyAccessor` implementors)
288
* **We now rely on Portable.BouncyCastle** for the ed25519 implementation. This means there is another DLL to reference when you use NetSparkle!
289
* **We now rely on System.Text.Json (netstandard2.0) OR Newtonsoft.Json (.NET Framework 4.5.2)** for the JSON items. This means there is another DLL to reference when you use NetSparkle, and it will change depending on if the `System.Text.Json` or `Newtonsoft.Json` item is used!
290

    
291
## Public Methods
292

    
293
### This section still needs to be updated for 2.0!
294

    
295
### SparkleUpdater(string appcastUrl, ISignatureVerifier signatureVerifier)
296

    
297
Initializes a new instance of the Sparkle class with the given appcast URL and signature verifier.
298

    
299
| Name | Description |
300
| ---- | ----------- |
301
| appcastUrl | *System.String*<br>the URL of the appcast file |
302
| signatureVerifier | *NetSparkle.Interfaces.ISIgnatureVerifier*<br>the object that will validate your app cast signatures |
303

    
304

    
305
### SparkleUpdater(string appcastUrl, ISignatureVerifier signatureVerifier, string referenceAssembly)
306

    
307
Initializes a new instance of the Sparkle class with the given appcast URL, signature verifier, and the name of the assembly to use when comparing update versions.
308

    
309
| Name | Description |
310
| ---- | ----------- |
311
| appcastUrl | *System.String*<br>the URL of the appcast file |
312
| signatureVerifier | *NetSparkle.Interfaces.ISIgnatureVerifier*<br>the object that will validate your app cast signatures |
313
| referenceAssembly | *System.String*<br>the name of the assembly to use for comparison when checking update versions |
314

    
315
### SparkleUpdater(string appcastUr, ISignatureVerifier signatureVerifier, string referenceAssembly, NetSparkle.Interfaces.IUIFactory factory)
316

    
317
Initializes a new instance of the Sparkle class with the given appcast URL, signature verifier, the name of the assembly to use when comparing update versions, and a UI factory to use in place of the default UI.
318

    
319
| Name | Description |
320
| ---- | ----------- |
321
| appcastUrl | *System.String*<br>the URL of the appcast file |
322
| signatureVerifier | *NetSparkle.Interfaces.ISIgnatureVerifier*<br>the object that will validate your app cast signatures |
323
| referenceAssembly | *System.String*<br>the name of the assembly to use for comparison when checking update versions |
324
| factory | *NetSparkle.Interfaces.IUIFactory*<br>a UI factory to use in place of the default UI |
325

    
326
### void CancelFileDownload()
327

    
328
Cancels an in-progress download and deletes the temporary file.
329

    
330
### Task<NetSparkle.SparkleUpdateInfo> CheckForUpdatesAtUserRequest()
331

    
332
Check for updates, using interaction appropriate for if the user just said "check for updates".
333

    
334
### Task<NetSparkle.SparkleUpdateInfo> CheckForUpdatesQuietly()
335

    
336
Check for updates, using interaction appropriate for where the user doesn't know you're doing it, so be polite.
337

    
338
### void CheckOnFirstApplicationIdle()
339

    
340
(WinForms only) Schedules an update check to happen on the first Application.Idle event.
341

    
342
### void Dispose()
343

    
344
Inherited from IDisposable. Stops all background activities.
345

    
346
### System.Uri GetAbsoluteUrl(string)
347

    
348
Creates a System.Uri from a URL string. If the URL is relative, converts it to an absolute URL based on the appcast URL.
349

    
350
| Name | Description |
351
| ---- | ----------- |
352
| url | *System.String*<br>relative or absolute URL |
353

    
354
### NetSparkle.Configuration GetApplicationConfig()
355

    
356
Reads the local Sparkle configuration for the given reference assembly.
357

    
358
### Task<NetSparkle.SparkleUpdateInfo> GetUpdateStatus(NetSparkle.Configuration config)
359

    
360
This method checks if an update is required. During this process the appcast will be downloaded and checked against the reference assembly. Ensure that the calling process has read access to the reference assembly. This method is also called from the background loops.
361

    
362
| Name | Description |
363
| ---- | ----------- |
364
| config | *NetSparkle.Configuration*<br>the NetSparkle configuration for the reference assembly |
365

    
366
**Returns**: NetSparkle.SparkleUpdateInfo with information on whether there is an update available or not.
367

    
368
### System.Net.WebResponse GetWebContentResponse(string url)
369

    
370
Used by NetSparkle.AppCast to fetch the appcast and DSA signature.
371

    
372
### System.IO.Stream GetWebContentStream(string url)
373

    
374
Used by NetSparkle.AppCast to fetch the appcast and DSA signature as a System.IO.Stream.
375

    
376
### void ShowUpdateNeededUI(bool isUpdateAlreadyDownloaded)
377

    
378
Shows the update UI with the latest downloaded update information.
379

    
380
| Name | Description |
381
| ---- | ----------- |
382
| isUpdateAlreadyDownloaded | *System.Boolean*<br>If true, make sure UI text shows that the user is about to install the file instead of download it. |
383

    
384
### void ShowUpdateNeededUI(NetSparkle.AppCastItem[], bool)
385

    
386
Shows the update needed UI with the given set of updates.
387

    
388
| Name | Description |
389
| ---- | ----------- |
390
| updates | *NetSparkle.AppCastItem[]*<br>updates to show UI for |
391
| isUpdateAlreadyDownloaded | *System.Boolean*<br>If true, make sure UI text shows that the user is about to install the file instead of download it. |
392

    
393
### void StartLoop(bool doInitialCheck)
394

    
395
Starts a NetSparkle background loop to check for updates every 24 hours.
396

    
397
You should only call this function when your app is initialized and shows its main window.
398

    
399
| Name | Description |
400
| ---- | ----------- |
401
| doInitialCheck | *System.Boolean*<br>whether the first check should happen before or after the first interval |
402

    
403
### void StartLoop(bool doInitialCheck, bool forceInitialCheck)
404

    
405
Starts a NetSparkle background loop to check for updates every 24 hours.
406

    
407
You should only call this function when your app is initialized and shows its main window.
408

    
409
| Name | Description |
410
| ---- | ----------- |
411
| doInitialCheck | *System.Boolean*<br>whether the first check should happen before or after the first interval |
412
| forceInitialCheck | *System.Boolean*<br>if doInitialCheck is true, whether the first check should happen even if the last check was less than 24 hours ago |
413

    
414
### void StartLoop(bool doInitialCheck, bool forceInitialCheck, System.TimeSpan checkFrequency)
415

    
416
Starts a NetSparkle background loop to check for updates on a given interval.
417

    
418
You should only call this function when your app is initialized and shows its main window.
419

    
420
| Name | Description |
421
| ---- | ----------- |
422
| doInitialCheck | *System.Boolean*<br>whether the first check should happen before or after the first period |
423
| forceInitialCheck | *System.Boolean*<br>if doInitialCheck is true, whether the first check should happen even if the last check was within the last checkFrequency interval |
424
| checkFrequency | *System.TimeSpan*<br>the interval to wait between update checks |
425

    
426
### void StartLoop(bool doInitialCheck, System.TimeSpan checkFrequency)
427

    
428
Starts a NetSparkle background loop to check for updates on a given interval.
429

    
430
You should only call this function when your app is initialized and shows its main window.
431

    
432
| Name | Description |
433
| ---- | ----------- |
434
| doInitialCheck | *System.Boolean*<br>whether the first check should happen before or after the first interval |
435
| checkFrequency | *System.TimeSpan*<br>the interval to wait between update checks |
436

    
437
### void StopLoop()
438

    
439
Stops the Sparkle background loop. Called automatically by [Dispose](#void-dispose).
440

    
441
## Public Properties
442

    
443
### This section still needs to be updated for 2.0!
444

    
445
- string [AppcastUrl](#string-appcasturl--get-set-) { get; set; }
446
- NetSparkle.CheckingForUpdatesWindow [CheckingForUpdatesWindow](#netsparklecheckingforupdateswindow-checkingforupdateswindow--get-set-) { get; set; }
447
- System.Action [ClearOldInstallers](#systemaction-clearoldinstallers--get-set-) { get; set; }
448
- NetSparkle.Configuration [Configuration](#netsparkleconfiguration-configuration--get-set-) { get; set; }
449
- string [CustomInstallerArguments](#string-custominstallerarguments--get-set-) { get; set; }
450
- NetSparkle.DSAChecker [DSAChecker](#netsparkledsachecker-dsachecker--get-set-) { get; set; }
451
- NetSparkle.LogWriter [LogWriter](#netsparklelogwriter-logwriter--get-set-) { get; set; }
452
- string [ExtraJsonData](#string-extrajsondata--get-set-) { get; set; }
453
- bool [HideReleaseNotes](#bool-hidereleasenotes--get-set-) { get; set; }
454
- bool [HideRemindMeLaterButton](#bool-hideremindmelaterbutton--get-set-) { get; set; }
455
- bool [HideSkipButton](#bool-hideskipbutton--get-set-) { get; set; }
456
- bool [IsUpdateLoopRunning](#bool-isupdatelooprunning--get-) { get; }
457
- NetSparkle.AppCastItem[] [LatestAppCastItems](#netsparkleappcastitem-latestappcastitems--get-) { get; }
458
- [PrintDiagnosticToConsole](#printdiagnostictoconsole--get-set-) { get; set; }
459
- NetSparkle.Interfaces.IDownloadProgress [ProgressWindow](#netsparkleinterfacesidownloadprogress-progresswindow--get-set-) { get; set; }
460
- bool [RelaunchAfterUpdate](#bool-relaunchafterupdate--get-set-) { get; set; }
461
- bool [ShowsUIOnMainThread](#bool-showsuionmainthread--get-set-) { get; set; }
462
- NetSparkle.Sparkle.UserInteractionMode [UserInteractionMode](#netsparklesparkleuserinteractionmode-silentmode--get-set-) { get; set; }
463
- string [TmpDownloadFilePath](#string-tmpdownloadfilepath--get-set-) { get; set; }
464
- bool [TrustEverySSLConnection](#bool-trusteverysslconnection--get-set-) { get; set; }
465
- NetSparkle.Interfaces.IUIFactory [UIFactory](#netsparkleinterfacesiuifactory-uifactory--get-set-) { get; set; }
466
- bool [UpdateMarkedCritical](#bool-updatemarkedcritical--get-) { get; }
467
- bool [UseNotificationToast](#bool-usenotificationtoast--get-set-) { get; set; }
468
- NetSparkle.Interfaces.IUpdateAvailable [UserWindow](#netsparkleinterfacesiupdateavailable-userwindow--get-set-) { get; set; }
469
- NetSparkle.SecurityProtocolType [SecurityProtocolType](#netsparklesecurityprotocoltype--get-set-) { get; set; }
470

    
471
### string AppcastUrl { get; set; }
472

    
473
Gets or sets the appcast URL
474

    
475
### NetSparkle.CheckingForUpdatesWindow CheckingForUpdatesWindow { get; set; }
476

    
477
The user interface window that shows the 'Checking for Updates...' form. TODO: Make this an interface so user can config their own UI
478

    
479
### System.Action ClearOldInstallers { get; set; }
480

    
481
Function that is called asynchronously to clean up old installers that have been downloaded with UserInteractionMode.DownloadNoInstall or UserInteractionMode.DownloadAndInstall.
482

    
483
### NetSparkle.Configuration Configuration { get; set; }
484

    
485
The NetSparkle configuration object for the current assembly.
486

    
487
### string CustomInstallerArguments { get; set; }
488

    
489
Run the downloaded installer with these arguments
490

    
491
### NetSparkle.DSAChecker DSAChecker { get; set; }
492

    
493
The DSA checker that verifies/validates downloaded files
494

    
495
### NetSparkle.LogWriter LogWriter { get; set; }
496

    
497
Logs diagnostic information to `Console.WriteLine` or `Debug.WriteLine` or wherever else the child class wants to report diagnostic information
498

    
499
### string ExtraJsonData { get; set; }
500

    
501
If not "", sends extra JSON via POST to server with the web request for update information and for the DSA signature.
502

    
503
### bool HideReleaseNotes { get; set; }
504

    
505
Hides the release notes view when an update is found.
506

    
507
### bool HideRemindMeLaterButton { get; set; }
508

    
509
Hides the remind me later button when an update is found.
510

    
511
### bool HideSkipButton { get; set; }
512

    
513
Hides the skip button view when an update is found.
514

    
515
### bool IsUpdateLoopRunning { get; }
516

    
517
Whether or not the update loop is running
518

    
519
### NetSparkle.AppCastItem[] LatestAppCastItems { get; }
520

    
521
Returns the latest appcast items to the caller. Might be null.
522

    
523
### PrintDiagnosticToConsole { get; set; }
524

    
525
If true, prints diagnostic messages to Console.WriteLine rather than Debug.WriteLine
526

    
527
### NetSparkle.Interfaces.IDownloadProgress ProgressWindow { get; set; }
528

    
529
The user interface window that shows a download progress bar, and then asks to install and relaunch the application
530

    
531
### bool RelaunchAfterUpdate { get; set; }
532

    
533
Defines if the application needs to be relaunched after executing the downloaded installer
534

    
535
### bool ShowsUIOnMainThread { get; set; }
536

    
537
WinForms only. If true, tries to run UI code on the main thread using System.Threading.SynchronizationContext.
538

    
539
### NetSparkle.Sparkle.UserInteractionMode SilentMode { get; set; }
540

    
541
Set the silent mode type for Sparkle to use when there is a valid update for the software
542

    
543
### string TmpDownloadFilePath { get; set; }
544

    
545
If set, downloads files to this path. If the folder doesn't already exist, creates the folder. Note that this variable is a path, not a full file name.
546

    
547
### bool TrustEverySSLConnection { get; set; }
548

    
549
If true, don't check the validity of SSL certificates
550

    
551
### NetSparkle.Interfaces.IUIFactory UIFactory { get; set; }
552

    
553
Factory for creating UI forms like progress window, etc.
554

    
555
### bool UpdateMarkedCritical { get; }
556

    
557
Loops through all of the most recently grabbed app cast items and checks if any of them are marked as critical
558

    
559
### bool UseNotificationToast { get; set; }
560

    
561
Specifies if you want to use the notification toast
562

    
563
### NetSparkle.Interfaces.IUpdateAvailable UserWindow { get; set; }
564

    
565
The user interface window that shows the release notes and asks the user to skip, later or update
566

    
567
### NetSparkle.SecurityProtocolType { get; set; }
568

    
569
The security protocol (`System.Net.SecurityProtocolType`) used by NetSparkle. Setting this property will also set this property for the current AppDomain of the caller. Needs to be set to `SecurityProtocolType.Tls12` for some cases, such as downloading something over HTTPS for a GitHub pages site.
570

    
571
## Public Events
572

    
573
### This section still needs to be updated for 2.0!
574

    
575
- [AboutToExitForInstallerRun](#abouttoexitforinstallerrun)
576
- [AboutToExitForInstallerRunAsync](#abouttoexitforinstallerrunasync)
577
- [CloseApplication](#closeapplication)
578
- [CloseApplicationAsync](#closeapplicationasync)
579
- [CheckLoopFinished](#checkloopfinished)
580
- [CheckLoopStarted](#checkloopstarted)
581
- [DownloadCanceled](#downloadcanceled)
582
- [DownloadedFileIsCorrupt](#downloadedfileiscorrupt)
583
- [DownloadedFileReady](#downloadedfileready)
584
- [DownloadError](#downloaderror)
585
- [FinishedDownloading](#finisheddownloading)
586
- [StartedDownloading](#starteddownloading)
587
- [UpdateCheckFinished](#updatecheckfinished)
588
- [UpdateCheckStarted](#updatecheckstarted)
589
- [UpdateDetected](#updatedetected)
590
- [UserSkippedVersion](#userskippedversion)
591
- [RemindMeLaterSelected](#remindmelaterselected)
592

    
593
### AboutToExitForInstallerRun
594

    
595
**Delegate**: void System.ComponentModel.CancelEventHandler(object sender, System.ComponentModel.CancelEventArgs e)
596

    
597
Subscribe to this to get a chance to shut down gracefully before quitting. If [AboutToExitForInstallerRunAsync](#abouttoexitforinstallerrunasync) is set, this has no effect.
598

    
599
### AboutToExitForInstallerRunAsync
600

    
601
**Delegate**: Task CancelEventHandlerAsync(object sender, System.ComponentModel.CancelEventArgs e)
602

    
603
Subscribe to this to get a chance to asynchronously shut down gracefully before quitting. This overrides [AboutToExitForInstallerRun](#abouttoexitforinstallerrun).
604

    
605
### CloseApplication
606

    
607
**Delegate**: void CloseApplication()
608

    
609
Event for custom shutdown logic. If this is set, it is called instead of Application.Current.Shutdown or Application.Exit. If [CloseApplicationAsync](#closeapplicationasync) is set, this has no effect.
610

    
611
**Warning**: The batch file that launches your executable only waits for 90 seconds before giving up! Make sure that your software closes within 90 seconds if you implement this event! If you need an event that can be canceled, use [AboutToExitForInstallerRun](#abouttoexitforinstallerrun).
612

    
613
### CloseApplicationAsync
614

    
615
**Delegate**: Task CloseApplicationAsync()
616

    
617
Event for custom shutdown logic. If this is set, it is called instead of Application.Current.Shutdown or Application.Exit. This overrides [CloseApplication](#closeapplication).
618

    
619
**Warning**: The batch file that launches your executable only waits for 90 seconds before giving up! Make sure that your software closes within 90 seconds if you implement this event! If you need an event that can be canceled, use [AboutToExitForInstallerRunAsync](#abouttoexitforinstallerrunasync).
620

    
621
### CheckLoopFinished
622

    
623
**Delegate**: void NetSparkle.LoopFinishedOperation(object sender, bool updateRequired)
624

    
625
This event will be raised when a check loop is finished
626

    
627
### CheckLoopStarted
628

    
629
**Delegate**: void NetSparkle.LoopStartedOperation(object sender)
630

    
631
This event will be raised when a check loop will be started
632

    
633
### DownloadCanceled
634

    
635
**Delegate**: void NetSparkle.DownloadEvent(string path)
636

    
637
Called when the download has been canceled
638

    
639
### DownloadedFileIsCorrupt
640

    
641
**Delegate**: void NetSparkle.DownloadedFileIsCorrupt(NetSparkle.AppCastItem item, string downloadPath)
642

    
643
Called when the downloaded file is downloaded (or at least partially on disk) and the DSA signature doesn't match. When this is called, Sparkle is not taking any further action to try to download the install file during this instance of the software. In order to make Sparkle try again, you must delete the file off disk yourself. Sparkle will try again after the software is restarted.
644

    
645
### DownloadedFileReady
646

    
647
**Delegate**: void NetSparkle.DownloadedFileReady(NetSparkle.AppCastItem item, string downloadPath)
648

    
649
Called when the downloaded file is fully downloaded and verified regardless of the value for SilentMode. Note that if you are installing fully silently, this will be called before the install file is executed, so don't manually initiate the file or anything.
650

    
651
### DownloadError
652

    
653
**Delegate**: void NetSparkle.DownloadEvent(string path)
654

    
655
Called when the download has downloaded but has an error other than corruption
656

    
657
### FinishedDownloading
658

    
659
**Delegate**: void NetSparkle.DownloadEvent(string path)
660

    
661
Called when the download has finished successfully
662

    
663
### StartedDownloading
664

    
665
**Delegate**: void NetSparkle.DownloadEvent(string path)
666

    
667
Called when the download has just started
668

    
669
### UpdateCheckFinished
670

    
671
**Delegate**: void NetSparkle.UpdateCheckFinished(object sender, NetSparkle.UpdateStatus status)
672

    
673
Called when update check is all done. May or may not have called [UpdateDetected](#updatedetected) in the middle.
674

    
675
### UpdateCheckStarted
676

    
677
**Delegate**: void NetSparkle.UpdateCheckStarted(object sender)
678

    
679
Called when update check has just started
680

    
681
### UpdateDetected
682

    
683
**Delegate**: void NetSparkle.UpdateDetected(object sender, NetSparkle.UpdateDetectedEventArgs e)
684

    
685
This event can be used to override the standard user interface process when an update is detected
686

    
687
### UserSkippedVersion
688

    
689
**Delegate**: void NetSparkle.UserSkippedVersion(NetSparkle.AppCastItem item, string downloadPath)
690

    
691
Called when the user skips some version of the application.
692

    
693
### RemindMeLaterSelected
694

    
695
**Delegate**: void NetSparkle.RemindMeLaterSelected(AppCastItem item);
696

    
697
Called when the user skips some version of the application by clicking the 'Remind Me Later' button
698

    
699
## License
700

    
701
NetSparkle is available under the [MIT License](LICENSE).
702

    
703
## Requirements
704

    
705
- .NET Framework 4.5.1+ OR .NET Core 3+
706

    
707
## Acknowledgements
708

    
709
* The original NetSparkle library, found at [dei79/netsparkle](https://github.com/dei79/netsparkle)
710
* A function for finding the base directory was taken from MIT-licensed [WalletWasabi](https://github.com/zkSNACKs/WalletWasabi/)
711
* MarkdownSharp is from [here](https://github.com/StackExchange/MarkdownSharp)
712

    
713
## Other Options
714

    
715
An incomplete list of other projects related to software updating:
716

    
717
- [Squirrel.Windows](https://github.com/Squirrel/Squirrel.Windows)
718
- [WinSparkle](https://github.com/vslavik/winsparkle)
719
- [NAppUpdate](https://github.com/synhershko/NAppUpdate)
720
- [AutoUpdater.NET](https://github.com/ravibpatel/AutoUpdater.NET)
클립보드 이미지 추가 (최대 크기: 500 MB)