Backend/e-suite.WorkBench/eSuite.WorkBench/Services/UpdateChecker.cs
2026-01-20 21:50:10 +00:00

148 lines
5.3 KiB
C#

using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Text;
namespace eSuite.WorkBench.Services
{
public static class StringExtensions
{
public static bool IsHigherVersion(this string currentValue, string potentialHigherValue)
{
var currentVersionSplit = currentValue.Split(".");
var potentialHigherValueSplit = potentialHigherValue.Split(".");
//Only checking the first three parts, as the revision is ignored by the MSI installer.
for( var i = 0; i < 3; i++)
{
if (int.Parse(currentVersionSplit[i]) < int.Parse(potentialHigherValueSplit[i]))
return true;
}
return false;
}
}
public interface IUpdateChecker
{
string GetCurrentVersion();
void CheckForUpdates(string devopsPersonalAccessKey);
}
public class UpdateChecker : IUpdateChecker
{
private readonly string _baseUrl = "https://dev.azure.com/sunbranding/f0f62be4-80fd-4c1c-93b6-d019ae74c8cd/_apis";
public string GetCurrentVersion()
{
var productAssembly = Assembly.GetEntryAssembly();
var thisAssemblyName = productAssembly.GetName();
var assemblyVersion = thisAssemblyName.Version.ToString();
return assemblyVersion;
}
public void CheckForUpdates(string devopsPersonalAccessKey)
{
if (!string.IsNullOrWhiteSpace(devopsPersonalAccessKey))
{
var authValue = Convert.ToBase64String(Encoding.UTF8.GetBytes($"esuite:{devopsPersonalAccessKey}"));
var message = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri($"{_baseUrl}/pipelines/88/runs?api-version=7.0"),
Headers =
{
{HttpRequestHeader.Authorization.ToString(), $"Basic {authValue}" }
}
};
try
{
var client = new HttpClient();
var response = client.Send(message).EnsureSuccessStatusCode();
var responseContent = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var buildPipelineResults = JsonConvert.DeserializeObject<BuildPipelineResponse>(responseContent);
var mostRecentBuild =
buildPipelineResults.Value.Where(x => x.Result == "succeeded" && x.State == "completed").MaxBy(x=> x.Id);
var mostRecentBuildVersion = ExtractVersion(mostRecentBuild.Name);
var currentRunningVersion = GetCurrentVersion();
if (currentRunningVersion.IsHigherVersion(mostRecentBuildVersion))
{
DownloadAndUpgrade(authValue, mostRecentBuild.Id);
}
}
catch (Exception)
{
//If the above check fails for any reason, I don't want to raise an exception, just fail silently, the update check will be skipped.
}
}
}
private void DownloadAndUpgrade(string authValue, long buildId)
{
//Download the Zip file
var message = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri($"{_baseUrl}/build/builds/{buildId}/artifacts?artifactName=installer&api-version=4.1&%24format=zip"),
Headers =
{
{HttpRequestHeader.Authorization.ToString(), $"Basic {authValue}" }
}
};
var client = new HttpClient();
var response = client.Send(message).EnsureSuccessStatusCode();
//Uncompress the Zip file
using var readStream = response.Content.ReadAsStream();
using var archive = new ZipArchive(readStream);
const string installerFilename = "eSuite.WorkBench.Installer.msi";
var installerArchiveEntry = archive.Entries.Single(x => x.Name == installerFilename);
using var unzippedMsi = installerArchiveEntry.Open();
var filePath = Path.Combine(Path.GetTempPath(), installerFilename);
//Delete old installer if found.
if (File.Exists(filePath))
File.Delete(filePath);
//Save the installer MSI
using Stream fs = File.Create(filePath);
unzippedMsi.CopyTo(fs);
fs.Flush();
fs.Close();
//Launch the msi
Process process = new Process();
// Configure the process using the StartInfo properties.
process.StartInfo.FileName = filePath;
process.StartInfo.UseShellExecute = true;
process.Start();
//shutdown
var currentProcess = Process.GetCurrentProcess();
currentProcess.Kill();
}
private string ExtractVersion(string name)
{
return name.Substring(2, name.IndexOf("-") - 2);
}
}
}