using System.Diagnostics; using System.IO; using System.Net.Http; using System.Text.Json.Nodes; namespace PamhagenSysCtrl.Helpers { public sealed record UpdateInstaller(Version Version, Uri Url, long Size); public static class UpdateService { private static readonly HttpClient HttpClient = new() { Timeout = Timeout.InfiniteTimeSpan, }; public static async Task GetLatestInstallerAsync(string feedUrl, CancellationToken cancellationToken = default) { using var response = await HttpClient.GetAsync(feedUrl, cancellationToken); response.EnsureSuccessStatusCode(); var json = JsonNode.Parse(await response.Content.ReadAsStringAsync(cancellationToken)); var latest = json!["data"]!.AsArray()[^1]!; return new( new Version((string)latest["version"]!), new Uri((string)latest["url"]!), (long)latest["size"]! ); } public static async Task DownloadInstallerAsync(UpdateInstaller installer, string targetDirectory, IProgress? progress = null, CancellationToken cancellationToken = default) { Directory.CreateDirectory(targetDirectory); var fileName = Path.Combine(targetDirectory, $"PamhagenSysCtrl-{installer.Version}.msi"); try { using var response = await HttpClient.GetAsync(installer.Url, HttpCompletionOption.ResponseHeadersRead, cancellationToken); response.EnsureSuccessStatusCode(); var contentLength = response.Content.Headers.ContentLength; await using (var destination = new FileStream(fileName, FileMode.Create)) { await using var source = await response.Content.ReadAsStreamAsync(cancellationToken); var buffer = new byte[81920]; long downloaded = 0; int read; while ((read = await source.ReadAsync(buffer, cancellationToken)) != 0) { await destination.WriteAsync(buffer.AsMemory(0, read), cancellationToken); downloaded += read; if (contentLength.HasValue) { progress?.Report((double)downloaded / contentLength.Value); } } } progress?.Report(1); return fileName; } catch { File.Delete(fileName); throw; } } public static void StartInstaller(string fileName) { var startInfo = new ProcessStartInfo { FileName = "msiexec.exe", UseShellExecute = true, Verb = "runas", }; startInfo.ArgumentList.Add("/i"); startInfo.ArgumentList.Add(Path.GetFullPath(fileName)); if (Process.Start(startInfo) == null) { throw new InvalidOperationException("Der Installer konnte nicht gestartet werden."); } } } }