From e0562c5e44a2c3d58e17ad2aaa53c72004107d22 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Thu, 10 Oct 2024 19:00:03 +0900 Subject: [PATCH 01/18] Add .NET 9 unit tests, building Totally untested. --- .github/workflows/publish-nuget.yml | 15 ++++++++++++--- .../NetSparkle.Tests.AppCastGenerator.csproj | 2 +- src/NetSparkle.Tests/NetSparkle.Tests.csproj | 2 +- .../NetSparkle.Tools.AppCastGenerator.csproj | 2 +- .../NetSparkle.Tools.DSAHelper.csproj | 2 +- .../NetSparkle.UI.Avalonia.csproj | 2 +- src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj | 2 +- .../NetSparkle.UI.WinForms.csproj | 2 +- src/NetSparkle/NetSparkle.csproj | 2 +- 9 files changed, 20 insertions(+), 11 deletions(-) diff --git a/.github/workflows/publish-nuget.yml b/.github/workflows/publish-nuget.yml index ea5289a2..c4feaa26 100644 --- a/.github/workflows/publish-nuget.yml +++ b/.github/workflows/publish-nuget.yml @@ -23,13 +23,14 @@ jobs: uses: microsoft/setup-msbuild@v2.0.0 if: matrix.os == 'windows-latest' - - name: Setup .NET 6.0, 7.0, 8.0 for tests + - name: Setup .NET 6.0, 7.0, 8.0, 9.0 for tests uses: actions/setup-dotnet@v4.0.1 with: dotnet-version: | 6.0.x 7.0.x 8.0.x + 9.0.x - name: Run NetSparkle.Tests in .NET 4.6.2 run: dotnet test -f net462 ${{ github.workspace }}/src/NetSparkle.Tests/NetSparkle.Tests.csproj @@ -53,6 +54,12 @@ jobs: - name: Run NetSparkle.Tests.AppCastGenerator in .NET 8 run: dotnet test -f net8.0 ${{ github.workspace }}/src/NetSparkle.Tests.AppCastGenerator/NetSparkle.Tests.AppCastGenerator.csproj + - name: Run NetSparkle.Tests in .NET 9 + run: dotnet test -f net9.0 ${{ github.workspace }}/src/NetSparkle.Tests/NetSparkle.Tests.csproj + + - name: Run NetSparkle.Tests.AppCastGenerator in .NET 9 + run: dotnet test -f net9.0 ${{ github.workspace }}/src/NetSparkle.Tests.AppCastGenerator/NetSparkle.Tests.AppCastGenerator.csproj + build: name: Build all packages as smoke test runs-on: windows-latest @@ -67,13 +74,14 @@ jobs: - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@v2.0.0 - - name: Setup .NET 6.0, 7.0, 8.0 + - name: Setup .NET 6.0, 7.0, 8.0, 9.0 uses: actions/setup-dotnet@v4.0.1 with: dotnet-version: | 6.0.x 7.0.x 8.0.x + 9.0.x - name: Clean things to be safe run: | @@ -113,13 +121,14 @@ jobs: - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@v2.0.0 - - name: Setup .NET 6.0, 7.0, 8.0 + - name: Setup .NET 6.0, 7.0, 8.0, 9.0 uses: actions/setup-dotnet@v4.0.1 with: dotnet-version: | 6.0.x 7.0.x 8.0.x + 9.0.x - name: Publish NetSparkleUpdater.SparkleUpdater on version change uses: nitz/publish-nuget@60fd3adf9d9eecc3bbf8a98738734d3061347172 diff --git a/src/NetSparkle.Tests.AppCastGenerator/NetSparkle.Tests.AppCastGenerator.csproj b/src/NetSparkle.Tests.AppCastGenerator/NetSparkle.Tests.AppCastGenerator.csproj index 94ee9d82..2df5e6d2 100644 --- a/src/NetSparkle.Tests.AppCastGenerator/NetSparkle.Tests.AppCastGenerator.csproj +++ b/src/NetSparkle.Tests.AppCastGenerator/NetSparkle.Tests.AppCastGenerator.csproj @@ -1,7 +1,7 @@ - net8.0;net7.0;net6.0 + net9.0;net8.0;net7.0;net6.0 false true diff --git a/src/NetSparkle.Tests/NetSparkle.Tests.csproj b/src/NetSparkle.Tests/NetSparkle.Tests.csproj index 8bc0f200..1476d100 100644 --- a/src/NetSparkle.Tests/NetSparkle.Tests.csproj +++ b/src/NetSparkle.Tests/NetSparkle.Tests.csproj @@ -3,7 +3,7 @@ {E50AC3A5-6C63-40D7-A4C4-9B359EFD5707} NetSparkleUnitTests NetSparkleUnitTests - net8.0;net7.0;net6.0;net462 + net9.0;net8.0;net7.0;net6.0;net462 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages diff --git a/src/NetSparkle.Tools.AppCastGenerator/NetSparkle.Tools.AppCastGenerator.csproj b/src/NetSparkle.Tools.AppCastGenerator/NetSparkle.Tools.AppCastGenerator.csproj index ec8bdea4..68c9d87a 100644 --- a/src/NetSparkle.Tools.AppCastGenerator/NetSparkle.Tools.AppCastGenerator.csproj +++ b/src/NetSparkle.Tools.AppCastGenerator/NetSparkle.Tools.AppCastGenerator.csproj @@ -4,7 +4,7 @@ Exe NetSparkleUpdater.AppCastGenerator NetSparkleUpdater.Tools.AppCastGenerator - net8.0;net7.0;net6.0 + net9.0;net8.0;net7.0;net6.0 true publish\ true diff --git a/src/NetSparkle.Tools.DSAHelper/NetSparkle.Tools.DSAHelper.csproj b/src/NetSparkle.Tools.DSAHelper/NetSparkle.Tools.DSAHelper.csproj index 033a9ffe..2b76e423 100644 --- a/src/NetSparkle.Tools.DSAHelper/NetSparkle.Tools.DSAHelper.csproj +++ b/src/NetSparkle.Tools.DSAHelper/NetSparkle.Tools.DSAHelper.csproj @@ -5,7 +5,7 @@ Exe NetSparkleUpdater.DSAHelper NetSparkleUpdater.Tools.DSAHelper - net8.0;net7.0;net6.0 + net9.0;net8.0;net7.0;net6.0 NetSparkle NetSparkleUpdater.Tools.DSAHelper Command line tool 'netsparkle-dsa' to generate and use DSA signatures. WARNING: DSA signatures are insecure. If possible, please use NetSparkleUpdater.Tools.AppCastGenerator instead to use ed25519 signatures. Use in conjunction with the NetSparkleUpdater library. diff --git a/src/NetSparkle.UI.Avalonia/NetSparkle.UI.Avalonia.csproj b/src/NetSparkle.UI.Avalonia/NetSparkle.UI.Avalonia.csproj index 8345214f..3385f550 100644 --- a/src/NetSparkle.UI.Avalonia/NetSparkle.UI.Avalonia.csproj +++ b/src/NetSparkle.UI.Avalonia/NetSparkle.UI.Avalonia.csproj @@ -1,7 +1,7 @@ - net8.0;net7.0;net6.0;netstandard2.0 + net9.0;net8.0;net7.0;net6.0;netstandard2.0 true NetSparkleUpdater.UI.Avalonia 3.0.0-preview20240921001 diff --git a/src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj b/src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj index f1d8aad0..4f231010 100644 --- a/src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj +++ b/src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj @@ -2,7 +2,7 @@ {6915843C-7947-4268-B569-6F5684651DF4} true - net8.0-windows;net7.0-windows;net6.0-windows;net462 + net9.0-windows;net8.0-windows;net7.0-windows;net6.0-windows;net462 NetSparkleUpdater.UI.WPF NetSparkleUpdater.UI.WPF Copyright © 2024 diff --git a/src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj b/src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj index 77ce5240..661434d1 100644 --- a/src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj +++ b/src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj @@ -4,7 +4,7 @@ NetSparkleUpdater.UI.WinForms NetSparkleUpdater.UI.WinForms true - net8.0-windows;net7.0-windows;net6.0-windows;net462 + net9.0-windows;net8.0-windows;net7.0-windows;net6.0-windows;net462 NetSparkle.NetFramework.WinForms NetSparkleUpdater.UI.WinForms Copyright © 2024 diff --git a/src/NetSparkle/NetSparkle.csproj b/src/NetSparkle/NetSparkle.csproj index b14c20dd..87647bc1 100644 --- a/src/NetSparkle/NetSparkle.csproj +++ b/src/NetSparkle/NetSparkle.csproj @@ -1,7 +1,7 @@  - net8.0;net7.0;net6.0;netstandard2.0;net462 + net9.0;net8.0;net7.0;net6.0;netstandard2.0;net462 true NetSparkleUpdater.SparkleUpdater 3.0.0-preview20240915001 From 68bf5a19a6cd13008bf32e4b278cf9fe3568c154 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Thu, 10 Oct 2024 19:07:00 +0900 Subject: [PATCH 02/18] Fix NET9 not defined --- src/NetSparkle.Tests/SparkleUpdaterFixture.cs | 2 +- src/NetSparkle/Configurations/RegistryConfiguration.cs | 6 +++--- src/NetSparkle/NetSparkle.csproj | 10 ++++++++++ src/NetSparkle/SparkleUpdater.cs | 4 ++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/NetSparkle.Tests/SparkleUpdaterFixture.cs b/src/NetSparkle.Tests/SparkleUpdaterFixture.cs index ce3ed654..83b6ad6d 100644 --- a/src/NetSparkle.Tests/SparkleUpdaterFixture.cs +++ b/src/NetSparkle.Tests/SparkleUpdaterFixture.cs @@ -4,7 +4,7 @@ using NetSparkleUpdater.AppCastHandlers; using NetSparkleUpdater.Interfaces; using Xunit; -#if (NETSTANDARD || NET5 || NET6 || NET7 || NET8) +#if (NETSTANDARD || NET5 || NET6 || NET7 || NET8 || NET9) using System.Runtime.InteropServices; #endif diff --git a/src/NetSparkle/Configurations/RegistryConfiguration.cs b/src/NetSparkle/Configurations/RegistryConfiguration.cs index f8d97f64..29bc0dec 100644 --- a/src/NetSparkle/Configurations/RegistryConfiguration.cs +++ b/src/NetSparkle/Configurations/RegistryConfiguration.cs @@ -2,7 +2,7 @@ using System.Globalization; using Microsoft.Win32; using NetSparkleUpdater.Interfaces; -#if (NETSTANDARD || NET6 || NET7 || NET8) +#if (NETSTANDARD || NET6 || NET7 || NET8 || NET9) using System.Runtime.InteropServices; #endif @@ -134,7 +134,7 @@ private DateTime ConvertStringToDate(string str) /// true if the items were loaded successfully; false otherwise private bool LoadValuesFromPath(string regPath) { -#if (NETSTANDARD || NET6 || NET7 || NET8) +#if (NETSTANDARD || NET6 || NET7 || NET8 || NET9) if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return false; @@ -206,7 +206,7 @@ private void SaveDidRunOnceAsTrue(string regPath) /// true if the values were saved to the registry; false otherwise private bool SaveValuesToPath(string regPath) { -#if (NETSTANDARD || NET6 || NET7 || NET8) +#if (NETSTANDARD || NET6 || NET7 || NET8 || NET9) if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return false; diff --git a/src/NetSparkle/NetSparkle.csproj b/src/NetSparkle/NetSparkle.csproj index 87647bc1..c3cbd044 100644 --- a/src/NetSparkle/NetSparkle.csproj +++ b/src/NetSparkle/NetSparkle.csproj @@ -82,6 +82,16 @@ ..\bin\Debug\NetSparkle\NetSparkle.xml DEBUG;TRACE;NETCORE;NET8 + + ..\bin\Release\NetSparkle\ + ..\bin\Release\NetSparkle\NetSparkle.xml + TRACE;NETCORE;NET9 + + + ..\bin\Debug\NetSparkle\ + ..\bin\Debug\NetSparkle\NetSparkle.xml + DEBUG;TRACE;NETCORE;NET9 + diff --git a/src/NetSparkle/SparkleUpdater.cs b/src/NetSparkle/SparkleUpdater.cs index ff1bf00c..873d65be 100644 --- a/src/NetSparkle/SparkleUpdater.cs +++ b/src/NetSparkle/SparkleUpdater.cs @@ -14,7 +14,7 @@ using NetSparkleUpdater.AppCastHandlers; using NetSparkleUpdater.AssemblyAccessors; using System.Text; -#if NETSTANDARD || NET6 || NET7 || NET8 +#if NETSTANDARD || NET6 || NET7 || NET8 || NET9 using System.Runtime.InteropServices; #endif @@ -246,7 +246,7 @@ public Configuration Configuration { if (_configuration == null) { -#if NETSTANDARD || NET6 || NET7 || NET8 +#if NETSTANDARD || NET6 || NET7 || NET8 || NET9 if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { _configuration = new RegistryConfiguration(new AssemblyDiagnosticsAccessor(_appReferenceAssembly)); From 2195e6a60e53621eb8fcc39de2735e66627c6cb6 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Thu, 10 Oct 2024 19:11:10 +0900 Subject: [PATCH 03/18] Bump System.Text.Json for netstandard2.0/net462 --- src/NetSparkle/NetSparkle.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NetSparkle/NetSparkle.csproj b/src/NetSparkle/NetSparkle.csproj index c3cbd044..f7e1cbc4 100644 --- a/src/NetSparkle/NetSparkle.csproj +++ b/src/NetSparkle/NetSparkle.csproj @@ -107,7 +107,7 @@ - + From 6c2c1ef9fbe00d9ff83e40c5f082f9a5388be970 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Fri, 11 Oct 2024 14:50:15 +0900 Subject: [PATCH 04/18] Fix wrong date in app cast test item --- src/NetSparkle.Tests/appcast_with_beta_items.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NetSparkle.Tests/appcast_with_beta_items.xml b/src/NetSparkle.Tests/appcast_with_beta_items.xml index 24fabbce..bc36f604 100644 --- a/src/NetSparkle.Tests/appcast_with_beta_items.xml +++ b/src/NetSparkle.Tests/appcast_with_beta_items.xml @@ -10,7 +10,7 @@ https://netsparkleupdater.github.io/NetSparkle/files/sample-app/2.1-release-notes.md - Fri, 28 Oct 2020 10:30:00 +0000 + Wed, 28 Oct 2020 10:30:00 +0000 Date: Fri, 11 Oct 2024 14:50:36 +0900 Subject: [PATCH 05/18] Fixed missing NET9 constants; wrong NET8 constants --- src/NetSparkle.Tests/NetSparkle.Tests.csproj | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/NetSparkle.Tests/NetSparkle.Tests.csproj b/src/NetSparkle.Tests/NetSparkle.Tests.csproj index 1476d100..ebca48d1 100644 --- a/src/NetSparkle.Tests/NetSparkle.Tests.csproj +++ b/src/NetSparkle.Tests/NetSparkle.Tests.csproj @@ -49,10 +49,16 @@ DEBUG;TRACE;NETCORE;NET7 - TRACE;NETCORE;NET7 + TRACE;NETCORE;NET8 - DEBUG;TRACE;NETCORE;NET7 + DEBUG;TRACE;NETCORE;NET8 + + + TRACE;NETCORE;NET9 + + + DEBUG;TRACE;NETCORE;NET9 From c606eba42a59c19c0c4c799dd98bf39aebdd7c38 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Fri, 11 Oct 2024 14:52:55 +0900 Subject: [PATCH 06/18] Bump Chaos.NaCl version for .NET 9 --- src/NetSparkle/NetSparkle.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NetSparkle/NetSparkle.csproj b/src/NetSparkle/NetSparkle.csproj index f7e1cbc4..a0cad8db 100644 --- a/src/NetSparkle/NetSparkle.csproj +++ b/src/NetSparkle/NetSparkle.csproj @@ -110,7 +110,7 @@ - + From 6fc10121c9c331806b8d6e989d1b74358136a7c7 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Fri, 11 Oct 2024 14:56:44 +0900 Subject: [PATCH 07/18] Rewrite ConvertStreamToByteArray to avoid CA2022 --- src/NetSparkle/Utilities.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/NetSparkle/Utilities.cs b/src/NetSparkle/Utilities.cs index b8d246f3..ed040958 100644 --- a/src/NetSparkle/Utilities.cs +++ b/src/NetSparkle/Utilities.cs @@ -146,10 +146,11 @@ public static string GetFullBaseDirectory() /// a byte[] array of the data in the given stream public static byte[] ConvertStreamToByteArray(Stream stream) { - // read the data - byte[] data = new byte[stream.Length]; - stream.Read(data, 0, data.Length); - return data; + using (MemoryStream ms = new MemoryStream()) + { + stream.CopyTo(ms); + return ms.ToArray(); + } } /// From 2cc212049cebda9139de7ebbc8a1ae695919bddf Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Fri, 11 Oct 2024 15:08:36 +0900 Subject: [PATCH 08/18] Deprecate SparkleUpdater SecurityProtocolType prop; don't use ServicePointManager --- UPGRADING.md | 1 + .../WebRequestAppCastDataDownloader.cs | 13 +++++++++++-- src/NetSparkle/SparkleUpdater.cs | 15 ++++++++++++--- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 640c6cca..d044d064 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -137,6 +137,7 @@ * Add `TrustEverySSLConnection` to .NET Core `WebFileDownloader` * Fix `WebFileDownloader` not setting up an `HttpClientHandler` (was always auto-redirect'ing before despite setting `RedirectHandler`; now behaves more similarly to `WebRequestAppCastDataDownloader`) * Fixed `Unsafe` mode in DSA/ed25519 checkers still checking signatures if a signature existed +* Deprecated `SecurityProtocolType SecurityProtocolType` property in `SparkleUpdater` (deprecated in .NET 9 and you can easily override the pertinent `HttpClient` behavior yourself) ## Updating from 0.X or 1.X to 2.X diff --git a/src/NetSparkle/Downloaders/WebRequestAppCastDataDownloader.cs b/src/NetSparkle/Downloaders/WebRequestAppCastDataDownloader.cs index 250836d1..c1c6c8cf 100644 --- a/src/NetSparkle/Downloaders/WebRequestAppCastDataDownloader.cs +++ b/src/NetSparkle/Downloaders/WebRequestAppCastDataDownloader.cs @@ -79,8 +79,12 @@ public async Task DownloadAndGetAppCastDataAsync(string url) { _appcastUrl = url; // configure ssl cert link + // .NET 9 -> ServicePointManager is deprecated + // we have the lambda below for trusting all connections anyway, so this + // is sort of redundant at the moment. +#if NETSTANDARD || NET6 || NET7 || NET8 ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate; - +#endif var handler = new HttpClientHandler(); if (RedirectHandler != null) { @@ -111,7 +115,10 @@ public async Task DownloadAndGetAppCastDataAsync(string url) if (response.IsSuccessStatusCode) { Stream responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + // .NET 9 -> ServicePointManager is deprecated +#if NETSTANDARD || NET6 || NET7 || NET8 ServicePointManager.ServerCertificateValidationCallback -= ValidateRemoteCertificate; +#endif using (StreamReader reader = new StreamReader(responseStream, GetAppCastEncoding())) { return await reader.ReadToEndAsync().ConfigureAwait(false); @@ -143,8 +150,10 @@ public async Task DownloadAndGetAppCastDataAsync(string url) } else { - Stream responseStream = await httpClient.GetStreamAsync(url).ConfigureAwait(false); + Stream responseStream = await httpClient.GetStreamAsync(url).ConfigureAwait(false);// .NET 9 -> ServicePointManager is deprecated +#if NETSTANDARD || NET6 || NET7 || NET8 ServicePointManager.ServerCertificateValidationCallback -= ValidateRemoteCertificate; +#endif using (StreamReader reader = new StreamReader(responseStream, GetAppCastEncoding())) { return await reader.ReadToEndAsync().ConfigureAwait(false); diff --git a/src/NetSparkle/SparkleUpdater.cs b/src/NetSparkle/SparkleUpdater.cs index 873d65be..e1e3eab2 100644 --- a/src/NetSparkle/SparkleUpdater.cs +++ b/src/NetSparkle/SparkleUpdater.cs @@ -149,11 +149,19 @@ public SparkleUpdater(string appcastUrl, ISignatureVerifier signatureVerifier, s #region Properties +#if NETSTANDARD || NET6 || NET7 || NET8 /// /// The security protocol used by NetSparkle. Setting this property will also set this - /// for the current AppDomain of the caller. Needs to be set to - /// SecurityProtocolType.Tls12 for some cases (such as when downloading from GitHub). - /// + /// for the current AppDomain of the caller. May need to be set to + /// SecurityProtocolType.Tls12 for some cases (such as when downloading from GitHub); + /// however, if your app is using a more recent version of .NET, you should be OK. + /// See also: https://stackoverflow.com/a/59398678/3938401 + /// .NET 9 -> ServicePointManager is deprecated + /// + [Obsolete("Deprecated in .NET 9; this property may be removed at any time " + + "(including minor/patch updates to this library); override pertinent " + + "functions (e.g. to HttpClient) in WebRequestAppCastDataDownloader or " + + "similar to make equivalent changes to your application")] public SecurityProtocolType SecurityProtocolType { get @@ -165,6 +173,7 @@ public SecurityProtocolType SecurityProtocolType ServicePointManager.SecurityProtocol = value; } } +#endif /// /// Set the user interaction mode for Sparkle to use when there is a valid update for the software From eadef099a3c85acb0130138d0043775503b78f88 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Wed, 16 Oct 2024 13:17:07 +0900 Subject: [PATCH 09/18] Add additional logs --- src/NetSparkle/SparkleUpdater.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/NetSparkle/SparkleUpdater.cs b/src/NetSparkle/SparkleUpdater.cs index e1e3eab2..98ad6636 100644 --- a/src/NetSparkle/SparkleUpdater.cs +++ b/src/NetSparkle/SparkleUpdater.cs @@ -853,6 +853,7 @@ private void ShowUpdateAvailableWindow(List updates, bool isUpdateA try { filename = await UpdateDownloader.RetrieveDestinationFileNameAsync(item); + LogWriter?.PrintMessage("Attempting to get download file name from server. This is what we got: {0} (is it null or whitespace? {1})", filename ?? "", string.IsNullOrWhiteSpace(filename)); } catch (Exception) { @@ -866,6 +867,7 @@ private void ShowUpdateAvailableWindow(List updates, bool isUpdateA try { filename = Path.GetFileName(new Uri(item.DownloadLink).LocalPath); + LogWriter?.PrintMessage("Attempting to get download file name based on link. This is what we got: {0} (is it null or whitespace? {1})", filename, string.IsNullOrWhiteSpace(filename)); } catch (UriFormatException) { From be65721aff54dfd3f6df459ed412d65db20f598a Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Wed, 16 Oct 2024 13:36:12 +0900 Subject: [PATCH 10/18] SparkleUpdater.GetDownloadPathForAppCastItem is virtual --- README.md | 1 + src/NetSparkle/SparkleUpdater.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a65e0901..1eb38212 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,7 @@ The file that launches your downloaded update executable only waits for 90 secon * `GetWindowsInstallerCommand` * `GetInstallerCommand` * `RunDownloadedInstaller` + * `GetDownloadPathForAppCastItem` * Override `UIFactory` if you don't want to implement the entirety of the `IUIFactory` interface yourself and just want to configure a function or two. To use an instance of your class, set `SparkleUpdater.UIFactory`. #### Using `IAppCastFilter` diff --git a/src/NetSparkle/SparkleUpdater.cs b/src/NetSparkle/SparkleUpdater.cs index 98ad6636..f8ad875f 100644 --- a/src/NetSparkle/SparkleUpdater.cs +++ b/src/NetSparkle/SparkleUpdater.cs @@ -837,7 +837,7 @@ private void ShowUpdateAvailableWindow(List updates, bool isUpdateA /// The item that you want to generate a download path for /// The download path for an app cast item if item is not null and has valid download link /// Otherwise returns null. - public async Task GetDownloadPathForAppCastItem(AppCastItem item) + public virtual async Task GetDownloadPathForAppCastItem(AppCastItem item) { if (item.DownloadLink != null) { From 3e151b9daecda54e5e87069a7f0f5aff46ca9c7e Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Wed, 16 Oct 2024 13:44:29 +0900 Subject: [PATCH 11/18] Add TmpDownloadFileNameWithExtension --- UPGRADING.md | 2 ++ src/NetSparkle/SparkleUpdater.cs | 28 +++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index d044d064..6d6a9b45 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -138,6 +138,8 @@ * Fix `WebFileDownloader` not setting up an `HttpClientHandler` (was always auto-redirect'ing before despite setting `RedirectHandler`; now behaves more similarly to `WebRequestAppCastDataDownloader`) * Fixed `Unsafe` mode in DSA/ed25519 checkers still checking signatures if a signature existed * Deprecated `SecurityProtocolType SecurityProtocolType` property in `SparkleUpdater` (deprecated in .NET 9 and you can easily override the pertinent `HttpClient` behavior yourself) +* `SparkleUpdater.GetDownloadPathForAppCastItem` is now marked `virtual` +* Added `TmpDownloadFileNameWithExtension` for controlling the download file name (use `TmpDownloadFilePath` to control the download file path) ## Updating from 0.X or 1.X to 2.X diff --git a/src/NetSparkle/SparkleUpdater.cs b/src/NetSparkle/SparkleUpdater.cs index f8ad875f..6a998dd9 100644 --- a/src/NetSparkle/SparkleUpdater.cs +++ b/src/NetSparkle/SparkleUpdater.cs @@ -58,6 +58,7 @@ public partial class SparkleUpdater : IDisposable private readonly EventWaitHandle _loopingHandle; private TimeSpan _checkFrequency; private string? _tmpDownloadFilePath; + private string? _tmpDownloadFileNameWithExtension; private string? _downloadTempFileName; private AppCastItem? _itemBeingDownloaded; private bool _hasAttemptedFileRedownload; @@ -183,7 +184,10 @@ public SecurityProtocolType SecurityProtocolType /// /// If set, downloads files to this path. If the folder doesn't already exist, creates /// the folder at download time (and not before). - /// Note that this variable is a path, not a full file name. + /// Note that this variable is a path, NOT a full file name. + /// By default, the file name is grabbed from the server and/or download link. + /// You can use to control + /// the actual file name (NOT path) if you wish. /// public string? TmpDownloadFilePath { @@ -191,6 +195,21 @@ public string? TmpDownloadFilePath set { _tmpDownloadFilePath = value?.Trim(); } } + /// + /// If set, downloads files to this file name. Note that this variable is a file name, not a path, + /// and it should not be treated as a path. Use to control + /// the download path. + /// If set, overrides any file name / extension grabbing from the server. + /// You probably want to set this manually before the item is downloaded to have some + /// unique filename + extension based on the item that's going to be downloaded, or a UUID + /// with extension, or similar. + /// + public string? TmpDownloadFileNameWithExtension + { + get { return _tmpDownloadFileNameWithExtension; } + set { _tmpDownloadFileNameWithExtension = value?.Trim(); } + } + /// /// Defines if the application needs to be relaunched after executing the downloaded installer /// @@ -841,14 +860,17 @@ private void ShowUpdateAvailableWindow(List updates, bool isUpdateA { if (item.DownloadLink != null) { - string? filename = string.Empty; + string? filename = string.IsNullOrWhiteSpace(TmpDownloadFileNameWithExtension) + ? string.Empty + : TmpDownloadFileNameWithExtension; // default to using the server's file name as the download file name if (UpdateDownloader is WebFileDownloader webFileDownloader) { webFileDownloader.PrepareToDownloadFile(); // reset download operations } - if (CheckServerFileName && UpdateDownloader != null) + if (string.IsNullOrWhiteSpace(filename) && CheckServerFileName && + UpdateDownloader != null) { try { From 126680bb18734cc8200effa4149dce5633358bb8 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Wed, 16 Oct 2024 13:45:38 +0900 Subject: [PATCH 12/18] Mark WebFileDownloader.RetrieveDestinationFileNameAsync virtual --- UPGRADING.md | 1 + src/NetSparkle/Downloaders/WebFileDownloader.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/UPGRADING.md b/UPGRADING.md index 6d6a9b45..56aef958 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -140,6 +140,7 @@ * Deprecated `SecurityProtocolType SecurityProtocolType` property in `SparkleUpdater` (deprecated in .NET 9 and you can easily override the pertinent `HttpClient` behavior yourself) * `SparkleUpdater.GetDownloadPathForAppCastItem` is now marked `virtual` * Added `TmpDownloadFileNameWithExtension` for controlling the download file name (use `TmpDownloadFilePath` to control the download file path) +* `WebFileDownloader.RetrieveDestinationFileNameAsync` is now marked `virtual` ## Updating from 0.X or 1.X to 2.X diff --git a/src/NetSparkle/Downloaders/WebFileDownloader.cs b/src/NetSparkle/Downloaders/WebFileDownloader.cs index 13bfb57b..7c173282 100644 --- a/src/NetSparkle/Downloaders/WebFileDownloader.cs +++ b/src/NetSparkle/Downloaders/WebFileDownloader.cs @@ -323,7 +323,7 @@ await httpClient.SendAsync(new HttpRequestMessage } /// - public async Task RetrieveDestinationFileNameAsync(AppCastItem item) + public virtual async Task RetrieveDestinationFileNameAsync(AppCastItem item) { if (item.DownloadLink == null) { From 2dd8c8b5ca60291552dad50b4b7eabc166bc5588 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Wed, 16 Oct 2024 13:46:51 +0900 Subject: [PATCH 13/18] Bump Avalonia version --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index f663e77a..7c3d4c8f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 11.1.3 + 11.1.4 From c9496281c52dbb7ee654c28cf754071ff2d29e85 Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Wed, 16 Oct 2024 13:50:06 +0900 Subject: [PATCH 14/18] Bump version --- .../NetSparkleUpdater.UI.WinForms.NetFramework.nuspec | 4 ++-- src/NetSparkle.UI.Avalonia/NetSparkle.UI.Avalonia.csproj | 2 +- src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj | 2 +- src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj | 2 +- src/NetSparkle/NetSparkle.csproj | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/nuget/winformsnetframework/NetSparkleUpdater.UI.WinForms.NetFramework.nuspec b/nuget/winformsnetframework/NetSparkleUpdater.UI.WinForms.NetFramework.nuspec index 8bd8790e..db30efc4 100644 --- a/nuget/winformsnetframework/NetSparkleUpdater.UI.WinForms.NetFramework.nuspec +++ b/nuget/winformsnetframework/NetSparkleUpdater.UI.WinForms.NetFramework.nuspec @@ -3,7 +3,7 @@ NetSparkleUpdater.UI.WinForms.NetFramework NetSparkleUpdater WinForms .NET Framework UI - 3.0.0-preview20240915001 + 3.0.0-preview20241016001 Deadpikle, Dirk Eisenberg Deadpikle README.md @@ -19,7 +19,7 @@ 2.0: See https://github.com/NetSparkleUpdater/NetSparkle for all information and to file issues/pull requests for and ask questions about this project. - + diff --git a/src/NetSparkle.UI.Avalonia/NetSparkle.UI.Avalonia.csproj b/src/NetSparkle.UI.Avalonia/NetSparkle.UI.Avalonia.csproj index 3385f550..7576a5c2 100644 --- a/src/NetSparkle.UI.Avalonia/NetSparkle.UI.Avalonia.csproj +++ b/src/NetSparkle.UI.Avalonia/NetSparkle.UI.Avalonia.csproj @@ -4,7 +4,7 @@ net9.0;net8.0;net7.0;net6.0;netstandard2.0 true NetSparkleUpdater.UI.Avalonia - 3.0.0-preview20240921001 + 3.0.0-preview20241016001 Deadpikle Deadpikle NetSparkleUpdater.UI.Avalonia diff --git a/src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj b/src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj index 4f231010..74caea28 100644 --- a/src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj +++ b/src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj @@ -13,7 +13,7 @@ https://github.com/NetSparkleUpdater/NetSparkle https://github.com/NetSparkleUpdater/NetSparkle.git git - 3.0.0-preview20240915001 + 3.0.0-preview20241016001 software-update-available.png NetSparkleUpdater/NetSparkle app updater framework with built-in WPF .NET Core and .NET Framework UI. NetSparkleUpdater/NetSparkle is a C# .NET software update framework that allows you to easily download installer files and update your C# .NET Framework or .NET Core software. Built-in UIs are available for WinForms, WPF, and Avalonia. You provide, somewhere on the internet, an XML appcast with software version information along with release notes in Markdown or HTML format. The NetSparkle framework then checks for an update in the background, displays the release notes to the user, and lets users download or skip the software update. The framework can also perform silent downloads so that you can present all of the UI yourself or set up your own silent software update system, as allowed by your software architecture. It was inspired by the Sparkle (https://sparkle-project.org/) project for Cocoa developers and the WinSparkle (https://winsparkle.org/) project (a Win32 port). diff --git a/src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj b/src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj index 661434d1..1bf34d5a 100644 --- a/src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj +++ b/src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj @@ -10,7 +10,7 @@ Copyright © 2024 ..\bin\$(Configuration)\NetSparkle.UI.WinForms\ - 3.0.0-preview20240915001 + 3.0.0-preview20241016001 Deadpikle Deadpikle NetSparkleUpdater/NetSparkle app updater framework with built-in WinForms UI. NetSparkleUpdater/NetSparkle is a C# .NET software update framework that allows you to easily download installer files and update your C# .NET Framework or .NET Core software. Built-in UIs are available for WinForms, WPF, and Avalonia. You provide, somewhere on the internet, an app cast with software version information along with release notes in Markdown or HTML format. The NetSparkle framework then checks for an update in the background, displays the release notes to the user, and lets users download or skip the software update. The framework can also perform silent downloads so that you can present all of the UI yourself or set up your own silent software update system, as allowed by your software architecture. It was inspired by the Sparkle (https://sparkle-project.org/) project for Cocoa developers and the WinSparkle (https://winsparkle.org/) project (a Win32 port). diff --git a/src/NetSparkle/NetSparkle.csproj b/src/NetSparkle/NetSparkle.csproj index a0cad8db..31b6d748 100644 --- a/src/NetSparkle/NetSparkle.csproj +++ b/src/NetSparkle/NetSparkle.csproj @@ -4,7 +4,7 @@ net9.0;net8.0;net7.0;net6.0;netstandard2.0;net462 true NetSparkleUpdater.SparkleUpdater - 3.0.0-preview20240915001 + 3.0.0-preview20241016001 Deadpikle, Dirk Eisenberg NetSparkleUpdater/NetSparkle is a C# .NET software update framework that allows you to easily download installer files and update your C# .NET Framework or .NET Core software. Built-in UIs are available for WinForms, WPF, and Avalonia; if you want a built-in UI, please reference a NetSparkleUpdater.UI package. You provide, somewhere on the internet, an XML appcast with software version information along with release notes in Markdown or HTML format. The NetSparkle framework then checks for an update in the background, displays the release notes to the user, and lets users download or skip the software update. The framework can also perform silent downloads so that you can present all of the UI yourself or set up your own silent software update system, as allowed by your software architecture. It was inspired by the Sparkle (https://sparkle-project.org/) project for Cocoa developers and the WinSparkle (https://winsparkle.org/) project (a Win32 port). Copyright 2010 - 2024 From 9de3120932b12f73244b52c149619807045e023d Mon Sep 17 00:00:00 2001 From: Deadpikle Date: Tue, 5 Nov 2024 18:27:56 +0900 Subject: [PATCH 15/18] Rough quick attempt at fix for WinForms .NET 9 --- src/NetSparkle.UI.WinForms/ToastNotifier.cs | 2 ++ src/NetSparkle.UI.WinForms/UpdateAvailableWindow.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/NetSparkle.UI.WinForms/ToastNotifier.cs b/src/NetSparkle.UI.WinForms/ToastNotifier.cs index 7043a568..5a935fb4 100644 --- a/src/NetSparkle.UI.WinForms/ToastNotifier.cs +++ b/src/NetSparkle.UI.WinForms/ToastNotifier.cs @@ -1,6 +1,7 @@ using NetSparkleUpdater.Properties; using System; using System.Collections.Generic; +using System.ComponentModel; using System.Drawing; using System.Windows.Forms; @@ -49,6 +50,7 @@ public ToastNotifier(Icon? applicationIcon = null) /// /// Action to perform when the user clicks on the toast window /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public Action ClickAction { get; set; } private void PauseTimerTick(object? sender, EventArgs e) diff --git a/src/NetSparkle.UI.WinForms/UpdateAvailableWindow.cs b/src/NetSparkle.UI.WinForms/UpdateAvailableWindow.cs index 99dfa755..d7eb0e1c 100644 --- a/src/NetSparkle.UI.WinForms/UpdateAvailableWindow.cs +++ b/src/NetSparkle.UI.WinForms/UpdateAvailableWindow.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using NetSparkleUpdater.Events; using NetSparkleUpdater.AppCastHandlers; +using System.ComponentModel; namespace NetSparkleUpdater.UI.WinForms { @@ -40,6 +41,7 @@ public partial class UpdateAvailableWindow : Form, IUpdateAvailable /// /// Object responsible for downloading and formatting markdown release notes for display in HTML /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public ReleaseNotesGrabber? ReleaseNotesGrabber { get; set; } private ISignatureVerifier? _signatureVerifier; From 5fd95d217694ae620953424a6b4710c541abf666 Mon Sep 17 00:00:00 2001 From: Deadpikle Date: Tue, 5 Nov 2024 18:30:57 +0900 Subject: [PATCH 16/18] Fix System.Drawing for .NET 9 --- src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj b/src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj index 74caea28..eb804295 100644 --- a/src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj +++ b/src/NetSparkle.UI.WPF/NetSparkle.UI.WPF.csproj @@ -52,13 +52,16 @@ - + - + - + + + + From ae12ed0e29fe69d6172db98d1e408e82a66c8044 Mon Sep 17 00:00:00 2001 From: Deadpikle Date: Tue, 5 Nov 2024 18:32:37 +0900 Subject: [PATCH 17/18] Bump some other packages --- src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj b/src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj index 1bf34d5a..19eec54d 100644 --- a/src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj +++ b/src/NetSparkle.UI.WinForms/NetSparkle.UI.WinForms.csproj @@ -95,14 +95,17 @@ true - + - + - + + + + From ba8267eb20965b294d70452235f8eb3ff3a04f81 Mon Sep 17 00:00:00 2001 From: Deadpikle Date: Tue, 5 Nov 2024 18:37:57 +0900 Subject: [PATCH 18/18] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1eb38212..67c27b9b 100644 --- a/README.md +++ b/README.md @@ -233,7 +233,7 @@ The file that launches your downloaded update executable only waits for 90 secon * Subclassing `JSONConfiguration` lets you quickly change the file path where data is saved via `GetSavePath` * Subclass `AppCastHelper` if you want full control over the app cast downloading and parsing process. Note that you can probably do everything you need to do via the `AppCastHelper` properties (including `IAppCastFilter AppCastFilter`), but subclassing will give you full, absolute control over the whole process. To use the instance of your class, set `SparkleUpdater.AppCastHelper`. * Subclass `ReleaseNotesGrabber` to control the release notes downloading (and therefore display) process. To use an instance of your class, set `UIFactory.ReleaseNotesGrabberOverride`. -* Override `WebFileDownloader` if you don't want to implement `IUpdateDownloader` yourself and just want to override a function or two such as `CreateHttpClient`. To use an instance of your class, set `SparkleUpdater.UpdateDownloader`. +* Override `WebFileDownloader` if you don't want to implement `IUpdateDownloader` yourself and just want to override a function or two such as `CreateHttpClient` or `RetreiveDestinationFileNameAsync`. To use an instance of your class, set `SparkleUpdater.UpdateDownloader`. * Override `WebRequestAppCastDataDownloader` if you don't want to implement `IAppCastDataDownloader` and just want to override a function or two such as `CreateHttpClient`. To use an instance of your class, set `SparkleUpdater.AppCastDataDownloader`. * Override `LogWriter` to implement the `PrintMessage` function; because `ILogger` is a pretty simple interface, you can probably just implement that interface yourself if your needs are complex. To use an instance of your class, set `SparkleUpdater.LogWriter`. * Override `SparkleUpdater` to implement some different installation-related functions, including: