diff --git a/changelog.md b/changelog.md
index 502905d2..f1dcc1b6 100644
--- a/changelog.md
+++ b/changelog.md
@@ -8,6 +8,7 @@ improvements may be omitted.)_
__[new features]__
+* Update support for Inno Setup is added.
* Update support for Stellarium is added.
## Version 2024.09.30.0
diff --git a/supported_applications.md b/supported_applications.md
index 71785527..b9d37b1d 100644
--- a/supported_applications.md
+++ b/supported_applications.md
@@ -27,6 +27,7 @@ application.
* HeidiSQL
* HexChat
* Inkscape
+* Inno Setup
* IrfanView
* KeePass 2
* LibreOffice
diff --git a/updater-test/software/InnoSetup_Tests.cs b/updater-test/software/InnoSetup_Tests.cs
new file mode 100644
index 00000000..f9f319ef
--- /dev/null
+++ b/updater-test/software/InnoSetup_Tests.cs
@@ -0,0 +1,70 @@
+/*
+ This file is part of the updater command line interface.
+ Copyright (C) 2024 Dirk Stolle
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using updater.software;
+
+namespace updater_test.software
+{
+ ///
+ /// Test cases for the InnoSetup class.
+ ///
+ [TestClass]
+ public class InnoSetup_Tests : BasicSoftwareTests
+ {
+ ///
+ /// Checks whether info() returns some meaningful data.
+ ///
+ [TestMethod]
+ public void Test_info()
+ {
+ _info(new InnoSetup(false));
+ }
+
+
+ ///
+ /// Checks whether the class implements the searchForNewer() method.
+ ///
+ [TestMethod]
+ public void Test_implementsSearchForNewer()
+ {
+ var inno = new InnoSetup(false);
+ Assert.IsTrue(inno.implementsSearchForNewer());
+ }
+
+
+ ///
+ /// Checks whether searchForNewer() returns something.
+ ///
+ [TestMethod]
+ public void Test_searchForNewer()
+ {
+ _searchForNewer(new InnoSetup(false));
+ }
+
+
+ ///
+ /// Checks whether the class info is up to date.
+ ///
+ [TestMethod]
+ public void Test_upToDate_info()
+ {
+ _upToDate_info(new InnoSetup(false));
+ }
+ } // class
+} // namespace
diff --git a/updater/software/All.cs b/updater/software/All.cs
index cca0d177..92c2eb55 100644
--- a/updater/software/All.cs
+++ b/updater/software/All.cs
@@ -89,6 +89,7 @@ private static List getUnfiltered(Options opts)
result.Add(new HexChat(autoGetNewer));
result.Add(new HeidiSQL(autoGetNewer));
result.Add(new Inkscape(autoGetNewer));
+ result.Add(new InnoSetup(autoGetNewer));
result.Add(new IrfanView(autoGetNewer));
result.Add(new KeePass(autoGetNewer));
result.Add(new LibreOffice(autoGetNewer));
diff --git a/updater/software/InnoSetup.cs b/updater/software/InnoSetup.cs
new file mode 100644
index 00000000..5a230ebc
--- /dev/null
+++ b/updater/software/InnoSetup.cs
@@ -0,0 +1,205 @@
+/*
+ This file is part of the updater command line interface.
+ Copyright (C) 2024 Dirk Stolle
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+using updater.data;
+
+namespace updater.software
+{
+ ///
+ /// Handles update of Inno Setup (Unicode version).
+ ///
+ public class InnoSetup: AbstractSoftware
+ {
+ ///
+ /// NLog.Logger for InnoSetup class
+ ///
+ private static readonly NLog.Logger logger = NLog.LogManager.GetLogger(typeof(InnoSetup).FullName);
+
+
+ ///
+ /// publisher name for signed installers of Inno Setup
+ ///
+ private const string publisherX509 = "CN=\"Open Source Developer, Martijn Laan\", O=Open Source Developer, L=Aalsmeer, S=Noord-Holland, C=NL";
+
+
+ ///
+ /// expiration date of certificate
+ ///
+ private static readonly DateTime certificateExpiration = new(2025, 4, 17, 9, 58, 13, DateTimeKind.Utc);
+
+
+ ///
+ /// Constructor.
+ ///
+ /// whether to automatically get
+ /// newer information about the software when calling the info() method
+ public InnoSetup(bool autoGetNewer)
+ : base(autoGetNewer)
+ { }
+
+
+ ///
+ /// Gets the currently known information about the software.
+ ///
+ /// Returns an AvailableSoftware instance with the known
+ /// details about the software.
+ public override AvailableSoftware knownInfo()
+ {
+ var installer = new InstallInfoExe(
+ "https://files.innosetup.nl/innosetup-6.3.3.exe",
+ HashAlgorithm.SHA256,
+ "0bcb2a409dea17e305a27a6b09555cabe600e984f88570ab72575cd7e93c95e6",
+ new Signature(publisherX509, certificateExpiration),
+ "/ALLUSERS /VERYSILENT /NORESTART");
+ return new AvailableSoftware("Inno Setup",
+ "6.3.3",
+ "^Inno Setup Version [0-9]+\\.[0-9]+\\.[0-9]+$",
+ "^Inno Setup Version [0-9]+\\.[0-9]+\\.[0-9]+$",
+ installer,
+ installer);
+ }
+
+
+ ///
+ /// Gets a list of IDs to identify the software.
+ ///
+ /// Returns a non-empty array of IDs, where at least one entry is unique to the software.
+ public override string[] id()
+ {
+ return new string[] { "inno-setup", "innosetup" };
+ }
+
+
+ ///
+ /// Determines whether the method searchForNewer() is implemented.
+ ///
+ /// Returns true, if searchForNewer() is implemented for that
+ /// class. Returns false, if not. Calling searchForNewer() may throw an
+ /// exception in the later case.
+ public override bool implementsSearchForNewer()
+ {
+ return true;
+ }
+
+
+ ///
+ /// Looks for newer versions of the software than the currently known version.
+ ///
+ /// Returns an AvailableSoftware instance with the information
+ /// that was retrieved from the net.
+ public override AvailableSoftware searchForNewer()
+ {
+ logger.Info("Searching for newer version of Inno Setup...");
+ var client = HttpClientProvider.Provide();
+ string response;
+ try
+ {
+ var task = client.GetStringAsync("https://jrsoftware.org/isdl.php");
+ task.Wait();
+ response = task.Result;
+ }
+ catch (Exception ex)
+ {
+ logger.Warn("Error while looking for newer Inno Setup version: " + ex.Message);
+ return null;
+ }
+
+ var regEx = new Regex("innosetup\\-([0-9]+\\.[0-9]+\\.[0-9]+)\\.exe");
+ var match = regEx.Match(response);
+ if (!match.Success)
+ return null;
+ string version = match.Groups[1].Value;
+ regEx = new Regex("sha256 hash: ([0-9a-f]{64})");
+ match = regEx.Match(response, match.Index);
+ if (!match.Success)
+ return null;
+ var checksum = match.Groups[1].Value;
+
+ var info = knownInfo();
+ info.install32Bit.checksum = checksum;
+ info.install32Bit.downloadUrl = info.install32Bit.downloadUrl.Replace(info.newestVersion, version);
+ info.install64Bit.checksum = checksum;
+ info.install64Bit.downloadUrl = info.install64Bit.downloadUrl.Replace(info.newestVersion, version);
+ info.newestVersion = version;
+ return info;
+ }
+
+
+ ///
+ /// Lists names of processes that might block an update, e.g. because
+ /// the application cannot be updated while it is running.
+ ///
+ /// currently installed / detected software version
+ /// Returns a list of process names that block the upgrade.
+ public override List blockerProcesses(DetectedSoftware detected)
+ {
+ return new List(4)
+ {
+ "Compil32",
+ "ISCC",
+ "islzma32",
+ "islzma64"
+ };
+ }
+
+
+ ///
+ /// Determines whether a separate process must be run before the update.
+ ///
+ /// currently installed / detected software version
+ /// Returns true, if a separate process returned by
+ /// preUpdateProcess() needs to run in preparation of the update.
+ /// Returns false, if not. Calling preUpdateProcess() may throw an
+ /// exception in the later case.
+ public override bool needsPreUpdateProcess(DetectedSoftware detected)
+ {
+ return true;
+ }
+
+
+ ///
+ /// Returns a process that must be run before the update.
+ ///
+ /// currently installed / detected software version
+ /// Returns a Process ready to start that should be run before
+ /// the update. May return null or may throw, if needsPreUpdateProcess()
+ /// returned false.
+ public override List preUpdateProcess(DetectedSoftware detected)
+ {
+ if (string.IsNullOrWhiteSpace(detected.installPath))
+ {
+ logger.Error("There is not enough information to uninstall the old Inno Setup version.");
+ return null;
+ }
+
+ // Remove enclosing quotes, if any.
+ if (detected.installPath.StartsWith("\"") && detected.installPath.EndsWith("\""))
+ {
+ detected.installPath = detected.installPath[1..^1];
+ }
+ var proc = new Process();
+ proc.StartInfo.FileName = System.IO.Path.Combine(detected.installPath, "unins000.exe");
+ proc.StartInfo.Arguments = "/VERYSILENT /NORESTART";
+ return new List(1) { proc };
+ }
+ }
+}