From a5cbbf1abce83de209f9d62a8fe2434f6b5cc85a Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Thu, 7 Dec 2023 14:54:02 +0900 Subject: [PATCH] Add InstallerProcessAboutToStart event Allows user to modify Process before it starts and optionally stop process from running --- UPGRADING.md | 1 + ...kleUpdater.UI.WinForms.NetFramework.nuspec | 4 +- .../NetSparkle.UI.Avalonia.csproj | 2 +- .../NetSparkle.UI.WPF.csproj | 2 +- .../NetSparkle.UI.WinForms.NetCore.csproj | 2 +- src/NetSparkle/NetSparkle.csproj | 2 +- src/NetSparkle/NetSparkleDelegates.cs | 11 ++++++ src/NetSparkle/SparkleUpdater.cs | 37 ++++++++++++++----- src/NetSparkle/SparkleUpdaterEvents.cs | 9 +++++ 9 files changed, 54 insertions(+), 16 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 6619e916..179b9be9 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -14,6 +14,7 @@ * Removed `netcoreapp3.1` and `net5.0` compatibility as they are both EOL per https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core (87381f2d3422e36fe5f614c85e43687eed497c42) * Moved to official/non-preview builds of `System.Drawing.Common` for 8.x and bump up to `8.0.0` for older versions of .NET (87381f2d3422e36fe5f614c85e43687eed497c42) [**] * Use `.axaml` in all Avalonia-related projects (46de3e9c9525cac4026a7959e44764752cdf36ee, e6d5ad20fec37e018a23ab46ef34d728b8104e96) +* `Exec(string cmd, bool waitForExit = true)` now returns a `bool`: `true` for the process starting, `false` otherwise **Changes/Fixes** diff --git a/nuget/winformsnetframework/NetSparkleUpdater.UI.WinForms.NetFramework.nuspec b/nuget/winformsnetframework/NetSparkleUpdater.UI.WinForms.NetFramework.nuspec index fbe47a05..f68782a6 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-preview20231207002 + 3.0.0-preview20231207003 Deadpikle, Dirk Eisenberg Deadpikle LICENSE.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 b28c4587..6c913859 100644 --- a/src/NetSparkle.UI.Avalonia/NetSparkle.UI.Avalonia.csproj +++ b/src/NetSparkle.UI.Avalonia/NetSparkle.UI.Avalonia.csproj @@ -4,7 +4,7 @@ net8.0;net7.0;net6.0;netstandard2.0 true NetSparkleUpdater.UI.Avalonia - 3.0.0-preview20231207002 + 3.0.0-preview20231207003 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 9ead3651..6e2f9585 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-preview20231207002 + 3.0.0-preview20231207003 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.NetCore/NetSparkle.UI.WinForms.NetCore.csproj b/src/NetSparkle.UI.WinForms.NetCore/NetSparkle.UI.WinForms.NetCore.csproj index 3e86ecc6..d991c471 100644 --- a/src/NetSparkle.UI.WinForms.NetCore/NetSparkle.UI.WinForms.NetCore.csproj +++ b/src/NetSparkle.UI.WinForms.NetCore/NetSparkle.UI.WinForms.NetCore.csproj @@ -10,7 +10,7 @@ Copyright © 2023 ..\bin\$(Configuration)\NetSparkle.UI.WinForms\ NetSparkleUpdater.UI.WinForms.NetCore - 3.0.0-preview20231207002 + 3.0.0-preview20231207003 Deadpikle Deadpikle NetSparkleUpdater/NetSparkle app updater framework with built-in WinForms .NET Core 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/NetSparkle.csproj b/src/NetSparkle/NetSparkle.csproj index 3b955a10..fbda122e 100644 --- a/src/NetSparkle/NetSparkle.csproj +++ b/src/NetSparkle/NetSparkle.csproj @@ -4,7 +4,7 @@ net8.0;net7.0;net6.0;netstandard2.0;net462 true NetSparkleUpdater.SparkleUpdater - 3.0.0-preview20231207002 + 3.0.0-preview20231207003 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 - 2023 diff --git a/src/NetSparkle/NetSparkleDelegates.cs b/src/NetSparkle/NetSparkleDelegates.cs index 0aa5a5ae..94eab54d 100644 --- a/src/NetSparkle/NetSparkleDelegates.cs +++ b/src/NetSparkle/NetSparkleDelegates.cs @@ -7,6 +7,7 @@ using System.Net.Http; using System.Text; using System.Threading.Tasks; +using System.Diagnostics; namespace NetSparkleUpdater { @@ -108,4 +109,14 @@ namespace NetSparkleUpdater /// The location that the redirect is pointing to /// The for the response from the server public delegate bool RedirectHandler(string fromURL, string toURL, HttpResponseMessage responseMessage); + + /// + /// A delegate to allow users to modify/see the installer process before it actually begins. + /// Return true to keep the installer process going, return false to cancel the installer process + /// (stop it from running). + /// + /// The installer process about to be started + /// The path to the downloaded installer that will be started by the new process + /// true if the installer should continue, false to stop the installer from starting + public delegate bool BeforeBeginInstallerProcess(Process process, string downloadFilePath); } diff --git a/src/NetSparkle/SparkleUpdater.cs b/src/NetSparkle/SparkleUpdater.cs index 304452f3..af95c59e 100644 --- a/src/NetSparkle/SparkleUpdater.cs +++ b/src/NetSparkle/SparkleUpdater.cs @@ -1566,6 +1566,7 @@ chcp 65001 > nul LogWriter.PrintMessage("Going to execute script at path: {0}", batchFilePath); // init the installer helper + var didStartInstaller = true; if (isWindows) { _installerProcess = new Process @@ -1579,16 +1580,24 @@ chcp 65001 > nul } }; // start the installer process. the batch file will wait for the host app to close before starting. - LogWriter.PrintMessage("Starting the installer process at {0}", batchFilePath); - _installerProcess.Start(); + var shouldContinue = InstallerProcessAboutToStart?.Invoke(_installerProcess, downloadFilePath) ?? true; + if (shouldContinue) + { + LogWriter.PrintMessage("Starting the installer process at {0}", batchFilePath); + _installerProcess.Start(); + } + else + { + didStartInstaller = false; + } } else { // on macOS need to use bash to execute the shell script LogWriter.PrintMessage("Starting the installer script process at {0} via shell exec", batchFilePath); - Exec(batchFilePath, false); // _installerProcess will be set up in `Exec` + didStartInstaller = Exec(batchFilePath, false); // _installerProcess will be set up in `Exec` } - if (ShouldKillParentProcessWhenStartingInstaller) + if (didStartInstaller && ShouldKillParentProcessWhenStartingInstaller) { await QuitApplication(); } @@ -1603,7 +1612,9 @@ chcp 65001 > nul /// /// Path to script to run via a shell /// True for the calling process to wait for the command to finish before exiting; false otherwise - protected void Exec(string cmd, bool waitForExit = true) + /// Optional param for download file that is being executed via installer + /// true if process started, false otherwise + protected bool Exec(string cmd, bool waitForExit = true, string downloadFilePath = "") { var escapedArgs = cmd.Replace("\"", "\\\""); var shell = ""; @@ -1631,13 +1642,19 @@ protected void Exec(string cmd, bool waitForExit = true) Arguments = $"-c \"{escapedArgs}\"" } }; - LogWriter.PrintMessage("Starting the process via {1} -c \"{0}\"", escapedArgs, shell); - _installerProcess.Start(); - if (waitForExit) + var shouldContinue = InstallerProcessAboutToStart?.Invoke(_installerProcess, downloadFilePath) ?? true; + if (shouldContinue) { - LogWriter.PrintMessage("Waiting for exit..."); - _installerProcess.WaitForExit(); + LogWriter.PrintMessage("Starting the process via {1} -c \"{0}\"", escapedArgs, shell); + _installerProcess.Start(); + if (waitForExit) + { + LogWriter.PrintMessage("Waiting for exit..."); + _installerProcess.WaitForExit(); + } + return true; } + return false; } /// diff --git a/src/NetSparkle/SparkleUpdaterEvents.cs b/src/NetSparkle/SparkleUpdaterEvents.cs index 8a4e3a06..5459a6d3 100644 --- a/src/NetSparkle/SparkleUpdaterEvents.cs +++ b/src/NetSparkle/SparkleUpdaterEvents.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Net; using System.Text; +using System.Diagnostics; namespace NetSparkleUpdater { @@ -112,5 +113,13 @@ public partial class SparkleUpdater : IDisposable /// If you need an event that can be canceled, use . /// public event CloseApplicationAsync CloseApplicationAsync; + + /// + /// Event to modify/see the installer process before it actually begins. You can set properties on the + /// before it by using this event. + /// Return true to keep the installer process going, return false to cancel the installer process + /// (stop it from running). + /// + public event BeforeBeginInstallerProcess InstallerProcessAboutToStart; } }