diff --git a/installer/AeroMCSetup.csproj b/installer/AeroMCSetup.csproj
new file mode 100644
index 0000000..1b0dd83
--- /dev/null
+++ b/installer/AeroMCSetup.csproj
@@ -0,0 +1,49 @@
+
+
+ WinExe
+
+ net48
+ true
+ true
+ latest
+ enable
+ enable
+ AnyCPU
+ false
+ false
+ AeroMC-Setup
+ AeroMCSetup
+ ..\src\assets\icon.ico
+ app.manifest
+ AeroMC Setup
+ AeroMC Setup
+ Installiert AeroMC
+ M_Viper
+ M_Viper
+ Copyright (c) M_Viper. Alle Rechte vorbehalten.
+ de-DE
+
+ 0.0.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/App.xaml b/installer/App.xaml
new file mode 100644
index 0000000..dc7754d
--- /dev/null
+++ b/installer/App.xaml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/App.xaml.cs b/installer/App.xaml.cs
new file mode 100644
index 0000000..be03d19
--- /dev/null
+++ b/installer/App.xaml.cs
@@ -0,0 +1,97 @@
+using System.IO;
+using System.Windows;
+using System.Windows.Media;
+using Microsoft.Win32;
+
+namespace AeroMCSetup;
+
+public partial class App : Application
+{
+ private static Mutex? _single;
+
+ protected override void OnStartup(StartupEventArgs e)
+ {
+ base.OnStartup(e);
+ bool has(string arg) => e.Args.Any(a => a.Equals(arg, StringComparison.OrdinalIgnoreCase));
+
+ // Das Deinstallationsprogramm ist das Setup ohne angehängte App → ohne Anhang immer Deinstallation
+ bool uninstall = has("--uninstall") || !Payload.Exists;
+ bool silent = has("/S");
+ bool update = has("--update");
+ bool launch = has("/launch");
+ var dirArg = e.Args.FirstOrDefault(a => a.StartsWith("/D=", StringComparison.OrdinalIgnoreCase))?.Substring(3);
+
+ _single = new Mutex(true, "AeroMC-Setup", out bool first);
+ if (!first)
+ {
+ Shutdown(0);
+ return;
+ }
+
+ // Stille Installation/Deinstallation für Skripte: AeroMC-Setup.exe /S [/D=Ordner] [/launch] bzw. --uninstall /S
+ if (silent)
+ {
+ var progress = new Progress<(double, string)>(_ => { });
+ try
+ {
+ if (uninstall) Installer.Uninstall(removeData: false, progress);
+ else
+ {
+ var dir = dirArg ?? Installer.InstalledDir ?? Installer.DefaultDir;
+ Installer.Install(dir, desktopLink: Installer.InstalledDir is null || Installer.DesktopLinkExists,
+ progress, waitForExit: true);
+ if (launch) System.Diagnostics.Process.Start(Path.Combine(dir, Installer.ExeName));
+ }
+ Shutdown(0);
+ }
+ catch (Exception ex)
+ {
+ // ohne Oberfläche: Fehler für Skripte nachvollziehbar ablegen
+ try { File.WriteAllText(Path.Combine(Path.GetTempPath(), "AeroMC-Setup.log"), $"[{DateTime.Now}] {ex}"); } catch { }
+ Shutdown(1);
+ }
+ return;
+ }
+
+ ApplyTheme();
+ var mode = uninstall ? SetupMode.Uninstall : update ? SetupMode.Update : SetupMode.Install;
+ new MainWindow(mode).Show();
+ }
+
+ protected override void OnExit(ExitEventArgs e)
+ {
+ try { _single?.ReleaseMutex(); } catch { }
+ base.OnExit(e);
+ }
+
+ /// Hell/Dunkel wie in Windows eingestellt.
+ private void ApplyTheme()
+ {
+ bool light = ReadDword(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme") != 0;
+ Resources.MergedDictionaries[0] = new ResourceDictionary
+ {
+ Source = new Uri($"pack://application:,,,/Themes/Colors.{(light ? "Light" : "Dark")}.xaml"),
+ };
+ if (!light)
+ {
+ // im Dunkeln etwas heller, damit Text und Fortschrittsbalken gut lesbar bleiben
+ var a = Color.FromRgb(0x4A, 0x86, 0xEA);
+ Resources["AccentBrush"] = new SolidColorBrush(a);
+ Resources["AccentHoverBrush"] = new SolidColorBrush(Color.FromRgb(0x5E, 0x94, 0xEE));
+ Resources["AccentSubtleBrush"] = new SolidColorBrush(Color.FromArgb(0x30, a.R, a.G, a.B));
+ Resources["AccentSubtleStrokeBrush"] = new SolidColorBrush(Color.FromArgb(0x60, a.R, a.G, a.B));
+ }
+ }
+
+ private static int ReadDword(string key, string name)
+ {
+ try
+ {
+ using var k = Registry.CurrentUser.OpenSubKey(key);
+ return k?.GetValue(name) is int i ? i : -1;
+ }
+ catch { return -1; }
+ }
+}
+
+public enum SetupMode { Install, Update, Uninstall }
diff --git a/installer/Installer.cs b/installer/Installer.cs
new file mode 100644
index 0000000..28d6f9a
--- /dev/null
+++ b/installer/Installer.cs
@@ -0,0 +1,501 @@
+using System.Diagnostics;
+using System.IO;
+using System.IO.Compression;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using Microsoft.Win32;
+
+namespace AeroMCSetup;
+
+/// Installation/Deinstallation – nur für den aktuellen Benutzer, ohne Administratorrechte.
+public static class Installer
+{
+ public const string AppName = "AeroMC";
+ public const string Publisher = "M_Viper";
+ public const string ExeName = "AeroMC.exe";
+ // Gleicher Name wie beim früheren NSIS-Setup: der Launcher erkennt daran eine Setup-Installation
+ // und bietet Updates als Setup an (src/updater.js → hasUninstaller).
+ public const string UninstallerName = "Uninstall AeroMC.exe";
+ // wie "appId" in package.json – gleiche Taskleisten-/Benachrichtigungs-Zuordnung wie bisher
+ public const string AppUserModelId = "com.aeromc.launcher";
+
+ // Schlüssel vom alten electron-builder-Setup übernommen → in "Apps" bleibt es ein einziger Eintrag
+ private const string KeyId = "12814222-87ee-5ae1-9e10-8eb2741fedd1";
+ private const string UninstallKey = @"Software\Microsoft\Windows\CurrentVersion\Uninstall\" + KeyId;
+ private const string LegacyAppKey = @"Software\" + KeyId;
+ private const string RunKey = @"Software\Microsoft\Windows\CurrentVersion\Run";
+ private const string FileListName = "install-files.txt";
+
+ public static string Version
+ {
+ get
+ {
+ var info = typeof(Installer).Assembly.GetCustomAttribute()?.InformationalVersion;
+ if (!string.IsNullOrEmpty(info)) return info!.Split('+')[0];
+ var v = typeof(Installer).Assembly.GetName().Version!;
+ return $"{v.Major}.{v.Minor}.{v.Build}";
+ }
+ }
+
+ /// Pfad dieses Setups (bzw. des Deinstallationsprogramms).
+ public static string SelfPath => Assembly.GetExecutingAssembly().Location;
+
+ public static string DefaultDir =>
+ Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Programs", AppName);
+
+ /// Launcher-Daten: Einstellungen, Konten, Java und (standardmäßig) die Instanzen.
+ public static string DataDir =>
+ Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "aeromc");
+
+ private static string StartMenuLink =>
+ Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Programs), AppName + ".lnk");
+
+ private static string DesktopLink =>
+ Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), AppName + ".lnk");
+
+ // ---------- vorhandene Installation ----------
+
+ private static string? RegValue(string name)
+ {
+ using var k = Registry.CurrentUser.OpenSubKey(UninstallKey);
+ return k?.GetValue(name) as string;
+ }
+
+ /// Ordner einer vorhandenen Installation (dieses Setups oder des alten NSIS-Setups), oder null.
+ public static string? InstalledDir
+ {
+ get
+ {
+ var dir = RegValue("InstallLocation");
+ if (string.IsNullOrWhiteSpace(dir))
+ {
+ // altes NSIS-Setup trägt keinen InstallLocation ein → aus dem Deinstallationsbefehl ablesen
+ var m = Regex.Match(RegValue("UninstallString") ?? "", "^\"([^\"]+)\"");
+ dir = m.Success ? Path.GetDirectoryName(m.Groups[1].Value) : null;
+ }
+ return dir is not null && File.Exists(Path.Combine(dir, ExeName)) ? dir : null;
+ }
+ }
+
+ /// Stammt die vorhandene Installation noch vom alten NSIS-Setup?
+ public static bool IsLegacyInstall =>
+ InstalledDir is not null && (RegValue("UninstallString") ?? "").IndexOf("--uninstall", StringComparison.OrdinalIgnoreCase) < 0;
+
+ public static string? InstalledVersion => RegValue("DisplayVersion");
+
+ public static bool DesktopLinkExists => File.Exists(DesktopLink);
+
+ public static bool IsRunning(string? dir) => AppProcesses(dir, InstalledDir).Any();
+
+ public static string LicenseText
+ {
+ get
+ {
+ using var s = typeof(Installer).Assembly.GetManifestResourceStream("LICENSE.txt");
+ if (s is null) return "";
+ using var r = new StreamReader(s);
+ return r.ReadToEnd().Trim();
+ }
+ }
+
+ /// Eigener Instanzen-Ordner außerhalb der Launcher-Daten (falls in den Einstellungen gesetzt), sonst null.
+ public static string? CustomInstancesDir
+ {
+ get
+ {
+ try
+ {
+ var json = File.ReadAllText(Path.Combine(DataDir, "settings.json"));
+ var m = Regex.Match(json, "\"instancesDir\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)\"");
+ if (!m.Success) return null;
+ var dir = Regex.Unescape(m.Groups[1].Value).Trim();
+ // liegt er doch in den Launcher-Daten (z. B. ausdrücklich der Standardordner), ist er nicht "eigen"
+ return dir.Length > 0 && !IsUnder(dir, DataDir) && !SamePath(dir, DataDir) ? dir : null;
+ }
+ catch { return null; }
+ }
+ }
+
+ // ---------- Installieren ----------
+
+ /// nach einem Update aus dem Launcher: ihm erst Zeit geben, sich selbst zu beenden
+ public static void Install(string dir, bool desktopLink, IProgress<(double, string)> progress, bool waitForExit = false)
+ {
+ if (!Environment.Is64BitOperatingSystem)
+ throw new InvalidOperationException("AeroMC benötigt ein 64-Bit-Windows (Windows 10 oder 11).");
+
+ var oldDir = InstalledDir;
+ progress.Report((0.02, "AeroMC wird beendet …"));
+ CloseRunningApp(waitForExit ? 20000 : 0, dir, oldDir);
+
+ using var zip = Payload.OpenArchive();
+ var topLevel = TopLevelNames(zip);
+
+ progress.Report((0.05, "Alte Version wird entfernt …"));
+ Directory.CreateDirectory(dir);
+ RemoveAppFiles(dir, topLevel);
+ if (oldDir is not null && !SamePath(oldDir, dir))
+ {
+ // Installation wurde in einen anderen Ordner verlegt → alten Ordner aufräumen
+ var oldExe = Path.Combine(oldDir, ExeName);
+ DeleteIfPointsTo(StartMenuLink, oldExe);
+ DeleteIfPointsTo(DesktopLink, oldExe);
+ RemoveAppFiles(oldDir, topLevel);
+ try { Directory.Delete(oldDir); } catch { } // nur wenn leer
+ }
+
+ Extract(zip, dir, p => progress.Report((0.08 + p * 0.8, "Dateien werden kopiert …")));
+
+ progress.Report((0.9, "Deinstallationsprogramm wird angelegt …"));
+ var exe = Path.Combine(dir, ExeName);
+ var uninstaller = Path.Combine(dir, UninstallerName);
+ if (!SamePath(SelfPath, uninstaller))
+ {
+ MoveAside(uninstaller);
+ CopyStub(uninstaller);
+ }
+ File.WriteAllLines(Path.Combine(dir, FileListName), topLevel.Concat([UninstallerName, FileListName]));
+
+ progress.Report((0.94, "Verknüpfungen werden angelegt …"));
+ Shortcut.Create(StartMenuLink, exe, "Minecraft-Launcher", AppUserModelId);
+ if (desktopLink) Shortcut.Create(DesktopLink, exe, "Minecraft-Launcher", AppUserModelId);
+ else DeleteIfPointsTo(DesktopLink, exe);
+
+ progress.Report((0.97, "Windows wird eingerichtet …"));
+ Registry.CurrentUser.DeleteSubKeyTree(UninstallKey, throwOnMissingSubKey: false); // Reste des alten Setups
+ Registry.CurrentUser.DeleteSubKeyTree(LegacyAppKey, throwOnMissingSubKey: false);
+ using (var k = Registry.CurrentUser.CreateSubKey(UninstallKey))
+ {
+ long size = DirSize(dir) / 1024;
+ k.SetValue("DisplayName", AppName);
+ k.SetValue("DisplayVersion", Version);
+ k.SetValue("Publisher", Publisher);
+ k.SetValue("DisplayIcon", $"{exe},0");
+ k.SetValue("InstallLocation", dir);
+ k.SetValue("UninstallString", $"\"{uninstaller}\" --uninstall");
+ k.SetValue("QuietUninstallString", $"\"{uninstaller}\" --uninstall /S");
+ k.SetValue("URLInfoAbout", "https://m-viper.de");
+ k.SetValue("InstallDate", DateTime.Now.ToString("yyyyMMdd"));
+ k.SetValue("EstimatedSize", (int)Math.Min(int.MaxValue, size), RegistryValueKind.DWord);
+ k.SetValue("NoModify", 1, RegistryValueKind.DWord);
+ k.SetValue("NoRepair", 1, RegistryValueKind.DWord);
+ }
+
+ progress.Report((1.0, "Fertig"));
+ }
+
+ private static List TopLevelNames(ZipArchive zip) =>
+ zip.Entries
+ .Select(e => e.FullName.Replace('\\', '/').Split('/')[0])
+ .Where(n => n.Length > 0)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
+
+ private static void Extract(ZipArchive zip, string dir, Action report)
+ {
+ var root = Path.GetFullPath(dir).TrimEnd('\\') + "\\";
+ long total = Math.Max(1, zip.Entries.Sum(e => e.Length)), done = 0;
+ var buffer = new byte[1 << 20];
+ int lastPercent = -1;
+
+ foreach (var entry in zip.Entries)
+ {
+ var target = Path.GetFullPath(Path.Combine(dir, entry.FullName));
+ if (!target.StartsWith(root, StringComparison.OrdinalIgnoreCase)) continue; // nie außerhalb des Ordners schreiben
+ if (entry.Name.Length == 0)
+ {
+ Directory.CreateDirectory(target);
+ continue;
+ }
+ Directory.CreateDirectory(Path.GetDirectoryName(target)!);
+ long before = done;
+ Retry(target, () =>
+ {
+ done = before;
+ MoveAside(target);
+ using var src = entry.Open();
+ using var dst = File.Create(target);
+ int n;
+ while ((n = src.Read(buffer, 0, buffer.Length)) > 0)
+ {
+ dst.Write(buffer, 0, n);
+ done += n;
+ int percent = (int)(done * 100 / total);
+ if (percent != lastPercent)
+ {
+ lastPercent = percent;
+ report(Math.Min(1.0, (double)done / total));
+ }
+ }
+ });
+ }
+ report(1.0);
+ }
+
+ /// Setup ohne angehängte App als Deinstallationsprogramm ablegen (nur ein paar hundert KB).
+ private static void CopyStub(string path)
+ {
+ long length = Payload.StubLength;
+ using var src = File.OpenRead(SelfPath);
+ using var dst = File.Create(path);
+ var buffer = new byte[81920];
+ long left = length;
+ while (left > 0)
+ {
+ int n = src.Read(buffer, 0, (int)Math.Min(buffer.Length, left));
+ if (n <= 0) break;
+ dst.Write(buffer, 0, n);
+ left -= n;
+ }
+ }
+
+ // ---------- Deinstallieren ----------
+
+ public static void Uninstall(bool removeData, IProgress<(double, string)> progress)
+ {
+ // Nur im eingetragenen Installationsordner löschen – nie dort, wo das Setup zufällig liegt (z. B. Downloads)
+ var dir = InstalledDir;
+ var exe = dir is null ? "" : Path.Combine(dir, ExeName);
+
+ progress.Report((0.1, "AeroMC wird beendet …"));
+ CloseRunningApp(0, dir);
+
+ progress.Report((0.3, "Verknüpfungen werden entfernt …"));
+ DeleteIfPointsTo(StartMenuLink, exe);
+ DeleteIfPointsTo(DesktopLink, exe);
+
+ progress.Report((0.45, "Windows-Einträge werden entfernt …"));
+ RemoveAutostart(exe);
+ Registry.CurrentUser.DeleteSubKeyTree(UninstallKey, throwOnMissingSubKey: false);
+ Registry.CurrentUser.DeleteSubKeyTree(LegacyAppKey, throwOnMissingSubKey: false);
+
+ if (removeData && Directory.Exists(DataDir))
+ {
+ progress.Report((0.6, "Instanzen, Konten und Einstellungen werden in den Papierkorb gelegt …"));
+ try
+ {
+ Microsoft.VisualBasic.FileIO.FileSystem.DeleteDirectory(DataDir,
+ Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs,
+ Microsoft.VisualBasic.FileIO.RecycleOption.SendToRecycleBin);
+ }
+ catch { }
+ }
+
+ progress.Report((0.8, "Dateien werden entfernt …"));
+ if (dir is null) { progress.Report((1.0, "Fertig")); return; }
+ RemoveAppFiles(dir, null);
+
+ // Das laufende Deinstallationsprogramm kann sich nicht selbst löschen → kurz nach dem Beenden per cmd.
+ // rmdir ohne /s entfernt den Ordner nur, wenn er danach leer ist.
+ var self = SelfPath;
+ if (IsUnder(self, dir))
+ {
+ Process.Start(new ProcessStartInfo("cmd.exe",
+ $"/c ping 127.0.0.1 -n 3 > nul & del /f /q \"{self}\" & del /f /q \"{Path.Combine(dir, "*.old")}\" & rmdir \"{dir}\"")
+ {
+ CreateNoWindow = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden,
+ });
+ }
+ else
+ {
+ TryDelete(Path.Combine(dir, UninstallerName));
+ try { Directory.Delete(dir); } catch { } // nur wenn leer
+ }
+ progress.Report((1.0, "Fertig"));
+ }
+
+ /// Autostart-Einträge entfernen, die der Launcher selbst gesetzt hat (Name vergibt Electron).
+ private static void RemoveAutostart(string exe)
+ {
+ if (exe.Length == 0) return;
+ using var run = Registry.CurrentUser.OpenSubKey(RunKey, writable: true);
+ if (run is null) return;
+ foreach (var name in run.GetValueNames())
+ {
+ if (run.GetValue(name) is string cmd && cmd.IndexOf(exe, StringComparison.OrdinalIgnoreCase) >= 0)
+ run.DeleteValue(name, throwOnMissingValue: false);
+ }
+ }
+
+ // ---------- Dateien ----------
+
+ ///
+ /// Entfernt die App-Dateien aus einem Installationsordner. Gelöscht wird nur, was nachweislich zu AeroMC gehört:
+ /// Einträge aus der Dateiliste der letzten Installation bzw. die Namen aus dem neuen Paket –
+ /// Ordner nur, wenn sie eindeutig von Electron stammen. Fremde Dateien im Ordner bleiben unangetastet.
+ ///
+ private static void RemoveAppFiles(string dir, IEnumerable? extraNames)
+ {
+ if (!Directory.Exists(dir)) return;
+ CleanupOldFiles(dir);
+ var listFile = Path.Combine(dir, FileListName);
+ var fromList = File.Exists(listFile) ? File.ReadAllLines(listFile).Where(l => l.Trim().Length > 0).ToList() : [];
+ var names = fromList.Concat(extraNames ?? []).Concat([UninstallerName, FileListName])
+ .Distinct(StringComparer.OrdinalIgnoreCase);
+
+ foreach (var name in names)
+ {
+ if (name.IndexOfAny(['\\', '/', ':']) >= 0 || name is "." or "..") continue;
+ var path = Path.Combine(dir, name);
+ if (SamePath(path, SelfPath)) continue; // das laufende Deinstallationsprogramm räumt cmd weg
+
+ if (Directory.Exists(path))
+ {
+ bool ours = fromList.Contains(name, StringComparer.OrdinalIgnoreCase)
+ || (name.Equals("resources", StringComparison.OrdinalIgnoreCase) && File.Exists(Path.Combine(path, "app.asar")))
+ || (name.Equals("locales", StringComparison.OrdinalIgnoreCase) && File.Exists(Path.Combine(path, "en-US.pak")));
+ if (ours) Retry(path, () => Directory.Delete(path, recursive: true));
+ }
+ else if (File.Exists(path))
+ {
+ Retry(path, () => MoveAside(path));
+ }
+ }
+ }
+
+ ///
+ /// Längster Pfad im Paket. Windows erlaubt (ohne Sonderfreigabe) nur 259 Zeichen pro Pfad –
+ /// der Installationsordner darf deshalb höchstens Zeichen lang sein.
+ ///
+ private static int? _longestEntry;
+ public static int MaxDirLength
+ {
+ get
+ {
+ if (_longestEntry is null)
+ {
+ try
+ {
+ using var zip = Payload.OpenArchive();
+ _longestEntry = zip.Entries.Count == 0 ? 0 : zip.Entries.Max(e => e.FullName.Length);
+ }
+ catch { _longestEntry = 0; }
+ }
+ return 259 - 1 - _longestEntry.Value;
+ }
+ }
+
+ private static void Retry(string path, Action action)
+ {
+ for (int attempt = 1; ; attempt++)
+ {
+ try
+ {
+ action();
+ return;
+ }
+ catch (PathTooLongException ex)
+ {
+ throw new IOException($"Der Installationsordner ist zu lang. Bitte einen kürzeren Ordner wählen (höchstens {MaxDirLength} Zeichen).", ex);
+ }
+ catch (Exception ex) when ((ex is IOException || ex is UnauthorizedAccessException) && attempt < 10)
+ {
+ Thread.Sleep(500);
+ }
+ catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException)
+ {
+ throw new IOException($"„{Path.GetFileName(path)}“ wird noch verwendet. Bitte AeroMC beenden " +
+ "(auch das Symbol im Infobereich neben der Uhr) und erneut versuchen.", ex);
+ }
+ }
+ }
+
+ ///
+ /// Vorhandene Datei löschen oder – falls sie noch geöffnet ist (Explorer, Virenscanner) – beiseite umbenennen.
+ /// Umbenennen klappt unter Windows auch bei geöffneten Dateien, überschreiben nicht.
+ ///
+ private static void MoveAside(string path)
+ {
+ if (!File.Exists(path)) return;
+ try { File.Delete(path); return; } catch { }
+ File.Move(path, $"{path}.{Guid.NewGuid():N}.old");
+ }
+
+ private static void CleanupOldFiles(string dir)
+ {
+ if (!Directory.Exists(dir)) return;
+ foreach (var f in Directory.GetFiles(dir, "*.old", SearchOption.AllDirectories))
+ try { File.Delete(f); } catch { }
+ }
+
+ private static void TryDelete(string path)
+ {
+ try { if (File.Exists(path)) File.Delete(path); } catch { }
+ }
+
+ private static void DeleteIfPointsTo(string link, string target)
+ {
+ if (!File.Exists(link) || target.Length == 0) return;
+ if (!SamePath(Shortcut.Target(link) ?? "", target)) return;
+ // Explorer/Indexdienst halten Verknüpfungen manchmal kurz fest → mehrmals versuchen
+ for (int i = 0; i < 10 && File.Exists(link); i++)
+ {
+ try { File.Delete(link); }
+ catch { Thread.Sleep(300); }
+ }
+ }
+
+ // ---------- Prozesse ----------
+
+ private static IEnumerable AppProcesses(params string?[] dirs)
+ {
+ var roots = dirs.Where(d => !string.IsNullOrEmpty(d)).Select(d => d!).ToList();
+ if (roots.Count == 0) yield break;
+ // Launcher (mehrere Electron-Prozesse) und ein evtl. laufendes ffmpeg der Aufzeichnung
+ foreach (var p in Process.GetProcessesByName("AeroMC").Concat(Process.GetProcessesByName("ffmpeg")))
+ {
+ string? file = null;
+ try { file = p.MainModule?.FileName; } catch { }
+ if (file is not null && roots.Any(r => IsUnder(file, r))) yield return p;
+ }
+ }
+
+ private static void CloseRunningApp(int waitMs, params string?[] dirs)
+ {
+ var until = DateTime.Now.AddMilliseconds(waitMs);
+ while (waitMs > 0 && DateTime.Now < until && AppProcesses(dirs).Any())
+ Thread.Sleep(300);
+
+ foreach (var p in AppProcesses(dirs).ToList())
+ {
+ try
+ {
+ p.Kill();
+ p.WaitForExit(10000);
+ }
+ catch { }
+ }
+ }
+
+ // ---------- Helfer ----------
+
+ private static bool SamePath(string a, string b)
+ {
+ try { return string.Equals(Path.GetFullPath(a).TrimEnd('\\'), Path.GetFullPath(b).TrimEnd('\\'), StringComparison.OrdinalIgnoreCase); }
+ catch { return false; }
+ }
+
+ private static bool IsUnder(string path, string dir) =>
+ Path.GetFullPath(path).StartsWith(Path.GetFullPath(dir).TrimEnd('\\') + "\\", StringComparison.OrdinalIgnoreCase);
+
+ private static long DirSize(string dir)
+ {
+ long sum = 0;
+ try
+ {
+ foreach (var f in Directory.EnumerateFiles(dir, "*", SearchOption.AllDirectories))
+ try { sum += new FileInfo(f).Length; } catch { }
+ }
+ catch { }
+ return sum;
+ }
+
+ public static long DataSize() => Directory.Exists(DataDir) ? DirSize(DataDir) : 0;
+
+ public static string FormatSize(long bytes) => bytes switch
+ {
+ < 1024 * 1024 => $"{Math.Max(1, bytes / 1024)} KB",
+ < 1024L * 1024 * 1024 => $"{bytes / 1024.0 / 1024:0.#} MB",
+ _ => $"{bytes / 1024.0 / 1024 / 1024:0.##} GB",
+ };
+}
diff --git a/installer/LauncherImport.cs b/installer/LauncherImport.cs
new file mode 100644
index 0000000..64b0505
--- /dev/null
+++ b/installer/LauncherImport.cs
@@ -0,0 +1,176 @@
+using System.IO;
+using System.Text;
+using System.Web.Script.Serialization;
+
+namespace AeroMCSetup;
+
+/// Ein gefundener anderer Launcher, dessen Instanzen AeroMC übernehmen kann.
+/// Kennung wie im Import-Dialog des Launchers: mc, cf, mmc, technic
+public sealed class FoundLauncher(string kind, string name, string path, int count, string unit)
+{
+ public string Kind { get; } = kind;
+ public string Name { get; } = name;
+ public string Path { get; } = path;
+ public int Count { get; } = count;
+ public string Unit { get; } = unit;
+}
+
+///
+/// Sucht andere Launcher an ihren üblichen Orten – nur lesend, es wird nichts verändert.
+/// Übernommen wird später im Launcher selbst (gleicher Import wie unter „Importieren“):
+/// das Setup legt dafür nur pending-import.json ab, AeroMC öffnet beim ersten Start
+/// den Import-Dialog damit fertig durchsucht.
+///
+public static class LauncherImport
+{
+ private static string AppData => Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
+ private static string Home => Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
+
+ private static string PendingFile => System.IO.Path.Combine(Installer.DataDir, "pending-import.json");
+
+ public static List Detect()
+ {
+ var found = new List();
+ void Add(Func probe)
+ {
+ try { if (probe() is { Count: > 0 } f) found.Add(f); } catch { /* unlesbar → einfach nicht anbieten */ }
+ }
+ Add(DetectMinecraftLauncher);
+ Add(DetectCurseForge);
+ Add(() => DetectMultiMc("Prism Launcher", System.IO.Path.Combine(AppData, "PrismLauncher")));
+ Add(() => DetectMultiMc("PolyMC", System.IO.Path.Combine(AppData, "PolyMC")));
+ // MultiMC (und portable Prism/PolyMC) liegen irgendwo – über ihre Verknüpfungen finden
+ foreach (var (name, root) in PortableMultiMcFromShortcuts())
+ {
+ if (found.Any(f => f.Kind == "mmc" && SamePath(f.Path, root))) continue;
+ Add(() => DetectMultiMc(name, root));
+ }
+ Add(DetectTechnic);
+ return found;
+ }
+
+ // ---------- offizieller Minecraft Launcher ----------
+
+ private static readonly string[] ProfileFiles =
+ ["launcher_profiles.json", "launcher_profiles_microsoft_store.json", "launcher_profiles_microsoft_store_2.json"];
+
+ private static FoundLauncher? DetectMinecraftLauncher()
+ {
+ var root = System.IO.Path.Combine(AppData, ".minecraft");
+ var file = ProfileFiles.Select(f => System.IO.Path.Combine(root, f)).FirstOrDefault(File.Exists);
+ if (file is null) return null;
+
+ var json = new JavaScriptSerializer { MaxJsonLength = int.MaxValue }
+ .Deserialize>(File.ReadAllText(file, Encoding.UTF8).TrimStart(''));
+ if (json?.TryGetValue("profiles", out var p) != true || p is not Dictionary profiles) return null;
+
+ // wie isImportableProfile in src/mcimport.js: die automatischen "Neueste Version"-Profile zählen nicht
+ int count = profiles.Values.OfType>().Count(profile =>
+ {
+ var type = (Get(profile, "type") ?? "").Trim().ToLowerInvariant();
+ if (type is "latest-release" or "latest-snapshot") return false;
+ return !string.IsNullOrWhiteSpace(Get(profile, "name")) || !string.IsNullOrWhiteSpace(Get(profile, "lastVersionId"));
+ });
+ return new FoundLauncher("mc", "Minecraft Launcher", root, count, count == 1 ? "Profil" : "Profile");
+ }
+
+ private static string? Get(Dictionary d, string key) => d.TryGetValue(key, out var v) ? v as string : null;
+
+ // ---------- CurseForge ----------
+
+ private static FoundLauncher? DetectCurseForge()
+ {
+ var dir = new[]
+ {
+ System.IO.Path.Combine(Home, "curseforge", "minecraft", "Instances"),
+ System.IO.Path.Combine(Home, "CurseForge", "minecraft", "Instances"),
+ }.FirstOrDefault(Directory.Exists);
+ if (dir is null) return null;
+
+ string[] markers = ["minecraftinstance.json", "instance.json", "mods", "config", "resourcepacks", "shaderpacks", "saves", "options.txt"];
+ int count = Directory.GetDirectories(dir).Count(d => markers.Any(m => Exists(d, m)));
+ return new FoundLauncher("cf", "CurseForge", dir, count, count == 1 ? "Instanz" : "Instanzen");
+ }
+
+ // ---------- Prism Launcher / PolyMC (MultiMC-Format) ----------
+
+ private static FoundLauncher? DetectMultiMc(string name, string root)
+ {
+ var instances = System.IO.Path.Combine(root, "instances");
+ if (!Directory.Exists(instances)) return null;
+ int count = Directory.GetDirectories(instances).Count(d => File.Exists(System.IO.Path.Combine(d, "instance.cfg")));
+ return new FoundLauncher("mmc", name, root, count, count == 1 ? "Instanz" : "Instanzen");
+ }
+
+ private static readonly Dictionary MultiMcExes = new(StringComparer.OrdinalIgnoreCase)
+ {
+ ["MultiMC.exe"] = "MultiMC",
+ ["prismlauncher.exe"] = "Prism Launcher",
+ ["polymc.exe"] = "PolyMC",
+ };
+
+ /// Ordner von MultiMC-artigen Launchern, auf die eine Verknüpfung (Desktop/Startmenü) zeigt.
+ private static IEnumerable<(string Name, string Root)> PortableMultiMcFromShortcuts()
+ {
+ var places = new[]
+ {
+ (Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), SearchOption.TopDirectoryOnly),
+ (Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory), SearchOption.TopDirectoryOnly),
+ (Environment.GetFolderPath(Environment.SpecialFolder.Programs), SearchOption.AllDirectories),
+ (Environment.GetFolderPath(Environment.SpecialFolder.CommonPrograms), SearchOption.AllDirectories),
+ };
+ var seen = new HashSet(StringComparer.OrdinalIgnoreCase);
+ foreach (var (dir, option) in places)
+ {
+ string[] links;
+ try { links = string.IsNullOrEmpty(dir) || !Directory.Exists(dir) ? [] : Directory.GetFiles(dir, "*.lnk", option); }
+ catch { continue; }
+ foreach (var link in links)
+ {
+ var target = Shortcut.Target(link);
+ if (string.IsNullOrEmpty(target) || !MultiMcExes.TryGetValue(System.IO.Path.GetFileName(target), out var name)) continue;
+ var root = System.IO.Path.GetDirectoryName(target);
+ if (root is null || !Directory.Exists(System.IO.Path.Combine(root, "instances")) || !seen.Add(root)) continue;
+ yield return (name, root);
+ }
+ }
+ }
+
+ private static bool SamePath(string a, string b) =>
+ string.Equals(System.IO.Path.GetFullPath(a).TrimEnd('\\'), System.IO.Path.GetFullPath(b).TrimEnd('\\'), StringComparison.OrdinalIgnoreCase);
+
+ // ---------- Technic ----------
+
+ private static FoundLauncher? DetectTechnic()
+ {
+ var modpacks = System.IO.Path.Combine(AppData, ".technic", "modpacks");
+ if (!Directory.Exists(modpacks)) return null;
+ string[] markers = ["bin", "mods", "config", "saves", "resourcepacks", "options.txt"];
+ int count = Directory.GetDirectories(modpacks).Count(d => markers.Any(m => Exists(d, m)));
+ return new FoundLauncher("technic", "Technic Launcher", modpacks, count, count == 1 ? "Modpack" : "Modpacks");
+ }
+
+ private static bool Exists(string dir, string name)
+ {
+ var p = System.IO.Path.Combine(dir, name);
+ return File.Exists(p) || Directory.Exists(p);
+ }
+
+ // ---------- Übergabe an den Launcher ----------
+
+ /// Merkt die ausgewählten Launcher für den ersten Start von AeroMC vor (oder räumt eine alte Vormerkung weg).
+ public static void WritePending(IReadOnlyCollection selected)
+ {
+ if (selected.Count == 0)
+ {
+ try { if (File.Exists(PendingFile)) File.Delete(PendingFile); } catch { }
+ return;
+ }
+ var data = new Dictionary
+ {
+ ["sources"] = selected.Select(s => new Dictionary { ["kind"] = s.Kind, ["path"] = s.Path }).ToList(),
+ };
+ Directory.CreateDirectory(Installer.DataDir);
+ File.WriteAllText(PendingFile, new JavaScriptSerializer().Serialize(data), new UTF8Encoding(false));
+ }
+}
diff --git a/installer/MainWindow.xaml b/installer/MainWindow.xaml
new file mode 100644
index 0000000..56a33ba
--- /dev/null
+++ b/installer/MainWindow.xaml
@@ -0,0 +1,368 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/MainWindow.xaml.cs b/installer/MainWindow.xaml.cs
new file mode 100644
index 0000000..eb7c90a
--- /dev/null
+++ b/installer/MainWindow.xaml.cs
@@ -0,0 +1,440 @@
+using System.Diagnostics;
+using System.IO;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Threading;
+
+namespace AeroMCSetup;
+
+public partial class MainWindow : Window
+{
+ private readonly SetupMode _mode;
+ private int _page;
+ private bool _busy;
+ private bool _done;
+ private string? _installedExe;
+ // andere Launcher für den optionalen Import (leer → Import-Schritt entfällt)
+ private List _found = [];
+ private bool HasImport => _found.Count > 0;
+
+ private const int PageNumImport = 3;
+ private const int PageNumProgress = 4;
+
+ public MainWindow(SetupMode mode)
+ {
+ InitializeComponent();
+ _mode = mode;
+ VersionText.Text = $"Version {Installer.Version}";
+ LicenseText.Text = Installer.LicenseText;
+
+ var installed = Installer.InstalledDir;
+ DirBox.Text = installed ?? Installer.DefaultDir;
+ DesktopLinkBox.IsChecked = installed is null || Installer.DesktopLinkExists;
+
+ if (installed is not null)
+ {
+ UpdateHint.Visibility = Visibility.Visible;
+ UpdateHintText.Text = Installer.InstalledVersion == Installer.Version
+ ? $"AeroMC {Installer.Version} ist bereits installiert und wird neu installiert. Deine Instanzen, Welten und Einstellungen bleiben erhalten."
+ : $"Die vorhandene Installation{(Installer.InstalledVersion is { } v ? $" (Version {v})" : "")} wird durch Version {Installer.Version} ersetzt. Deine Instanzen, Welten und Einstellungen bleiben erhalten.";
+ }
+ if (Installer.IsRunning(installed)) RunningHint.Visibility = Visibility.Visible;
+
+ switch (mode)
+ {
+ case SetupMode.Uninstall:
+ Title = WindowTitle.Text = "AeroMC deinstallieren";
+ Steps.Visibility = Visibility.Collapsed;
+ ShowOnly(PageUninstall);
+ NextButton.Content = "Deinstallieren";
+ BackButton.Visibility = Visibility.Collapsed;
+ LoadDataInfo();
+ break;
+ case SetupMode.Update:
+ // aus dem Launcher heraus: ohne Rückfragen direkt aktualisieren und danach wieder starten
+ Title = WindowTitle.Text = "AeroMC wird aktualisiert";
+ Steps.Visibility = Visibility.Collapsed;
+ Loaded += async (_, _) => await RunInstall(DirBox.Text, DesktopLinkBox.IsChecked == true, update: true);
+ ShowOnly(PageProgress);
+ ProgressTitle.Text = "AeroMC wird aktualisiert …";
+ BackButton.Visibility = Visibility.Hidden;
+ break;
+ default:
+ SetupImportPage();
+ ShowPage(0);
+ break;
+ }
+ }
+
+ // ---------- Seiten ----------
+
+ private UIElement? _shownPage;
+
+ /// Seite wechseln – mit kurzem Einblenden von rechts.
+ private void ShowOnly(UIElement page)
+ {
+ foreach (var p in new UIElement[] { PageWelcome, PageLicense, PageOptions, PageImport, PageProgress, PageUninstall })
+ p.Visibility = p == page ? Visibility.Visible : Visibility.Collapsed;
+ if (page == _shownPage) return;
+ _shownPage = page;
+
+ var ease = new CubicEase { EasingMode = EasingMode.EaseOut };
+ var slide = new TranslateTransform(18, 0);
+ page.RenderTransform = slide;
+ slide.BeginAnimation(TranslateTransform.XProperty, new DoubleAnimation(18, 0, TimeSpan.FromMilliseconds(260)) { EasingFunction = ease });
+ page.BeginAnimation(OpacityProperty, new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(220)));
+ }
+
+ // Farben der Schritt-Anzeige in der (immer dunkelblauen) Seitenleiste
+ private static readonly Brush StepDoneFill = Frozen(Color.FromRgb(0x4A, 0x86, 0xEA));
+ private static readonly Brush StepCurrentFill = Brushes.White;
+ private static readonly Brush StepCurrentText = Frozen(Color.FromRgb(0x1C, 0x4E, 0xB8));
+ private static readonly Brush StepUpcoming = Frozen(Color.FromRgb(0x7F, 0x95, 0xC2));
+ private static readonly Brush StepUpcomingStroke = Frozen(Color.FromRgb(0x46, 0x5E, 0x92));
+ private static readonly Brush StepDoneText = Frozen(Color.FromRgb(0xB9, 0xC8, 0xE8));
+ private static readonly Brush StepLineIdle = Frozen(Color.FromRgb(0x2E, 0x45, 0x78));
+
+ private static Brush Frozen(Color c)
+ {
+ var b = new SolidColorBrush(c);
+ b.Freeze();
+ return b;
+ }
+
+ private void UpdateSteps(int page)
+ {
+ var dots = new[] { Dot0, Dot1, Dot2, Dot3, Dot4 };
+ var nums = new[] { Num0, Num1, Num2, Num3, Num4 };
+ var labels = new[] { Label0, Label1, Label2, Label3, Label4 };
+ var lines = new[] { Line0, Line1, Line2, Line3 };
+ var iconFont = (FontFamily)FindResource("IconFont");
+ var uiFont = (FontFamily)FindResource("UiFont");
+
+ // ohne gefundene Launcher fällt der Import-Schritt weg → Nummern rücken auf
+ ImportStepRow.Visibility = Line3.Visibility = HasImport ? Visibility.Visible : Visibility.Collapsed;
+ int number = 0;
+ for (int i = 0; i < dots.Length; i++)
+ {
+ if (i == PageNumImport && !HasImport) continue;
+ number++;
+ bool done = i < page || (_done && i == page);
+ bool current = i == page && !done;
+ dots[i].Background = done ? StepDoneFill : current ? StepCurrentFill : Brushes.Transparent;
+ dots[i].BorderBrush = done ? StepDoneFill : current ? StepCurrentFill : StepUpcomingStroke;
+ nums[i].Text = done ? "" : number.ToString();
+ nums[i].FontFamily = done ? iconFont : uiFont;
+ nums[i].FontSize = done ? 11 : 12;
+ nums[i].Foreground = done ? Brushes.White : current ? StepCurrentText : StepUpcoming;
+ labels[i].Foreground = current ? Brushes.White : done ? StepDoneText : StepUpcoming;
+ labels[i].FontWeight = current ? FontWeights.SemiBold : FontWeights.Normal;
+ }
+ for (int i = 0; i < lines.Length; i++)
+ lines[i].Background = i < page ? StepDoneFill : StepLineIdle;
+ }
+
+ private void ShowPage(int page)
+ {
+ _page = page;
+ ShowOnly(page switch { 0 => PageWelcome, 1 => PageLicense, 2 => PageOptions, PageNumImport => PageImport, _ => PageProgress });
+ UpdateSteps(page);
+
+ BackButton.Visibility = page is 1 or 2 or PageNumImport ? Visibility.Visible : Visibility.Hidden;
+ NextButton.Content = page switch
+ {
+ 2 => HasImport ? "Weiter" : "Installieren",
+ PageNumImport => "Installieren",
+ PageNumProgress => "Fertigstellen",
+ _ => "Weiter",
+ };
+ NextButton.IsEnabled = page != 1 || AcceptLicense.IsChecked == true;
+ }
+
+ private void AcceptLicense_Click(object sender, RoutedEventArgs e) => NextButton.IsEnabled = AcceptLicense.IsChecked == true;
+
+ private void Back_Click(object sender, RoutedEventArgs e)
+ {
+ if (!_busy && _page > 0) ShowPage(_page - 1);
+ }
+
+ private async void Next_Click(object sender, RoutedEventArgs e)
+ {
+ if (_busy) return;
+
+ if (_mode == SetupMode.Uninstall)
+ {
+ if (_done) { Close(); return; }
+ await RunUninstall();
+ return;
+ }
+ if (_mode == SetupMode.Update)
+ {
+ Close(); // nur nach einem Fehler erreichbar
+ return;
+ }
+
+ switch (_page)
+ {
+ case 0: ShowPage(1); break;
+ case 1 when AcceptLicense.IsChecked == true: ShowPage(2); break;
+ case 2:
+ var dir = DirBox.Text.Trim();
+ if (!IsFullPath(dir) || dir.IndexOfAny(Path.GetInvalidPathChars()) >= 0)
+ {
+ MessageBox.Show(this, "Bitte einen gültigen Ordner angeben, z. B. C:\\Spiele\\AeroMC.", "AeroMC Setup");
+ return;
+ }
+ if (dir.TrimEnd('\\', '/').Length > Installer.MaxDirLength)
+ {
+ MessageBox.Show(this, $"Der Ordnerpfad ist zu lang ({dir.TrimEnd('\\', '/').Length} Zeichen). Windows erlaubt hier höchstens " +
+ $"{Installer.MaxDirLength} Zeichen – bitte einen kürzeren Ordner wählen, z. B. C:\\Spiele\\AeroMC.", "AeroMC Setup");
+ return;
+ }
+ if (HasImport) ShowPage(PageNumImport);
+ else await RunInstall(dir, DesktopLinkBox.IsChecked == true, update: false);
+ break;
+ case PageNumImport:
+ await RunInstall(DirBox.Text.Trim(), DesktopLinkBox.IsChecked == true, update: false);
+ break;
+ case PageNumProgress:
+ if (LaunchBox.IsChecked == true) StartApp();
+ Close();
+ break;
+ }
+ }
+
+ // ---------- Import aus anderen Launchern ----------
+
+ private void SetupImportPage()
+ {
+ try { _found = LauncherImport.Detect(); } catch { _found = []; }
+ ImportList.Children.Clear();
+ for (int i = 0; i < _found.Count; i++)
+ {
+ var f = _found[i];
+ var text = new StackPanel { Margin = new Thickness(4, 0, 0, 0) };
+ text.Children.Add(new TextBlock { Text = f.Name, FontWeight = FontWeights.SemiBold });
+ var detail = new TextBlock
+ {
+ Text = $"{f.Count} {f.Unit} gefunden · {f.Path}",
+ FontSize = 12,
+ Margin = new Thickness(0, 2, 0, 0),
+ TextTrimming = TextTrimming.CharacterEllipsis,
+ ToolTip = f.Path,
+ };
+ detail.SetResourceReference(TextBlock.ForegroundProperty, "TextSecondaryBrush");
+ text.Children.Add(detail);
+
+ var box = new CheckBox { Content = text, Tag = f, Margin = new Thickness(0, 10, 0, 10), IsChecked = false };
+ if (i > 0)
+ {
+ var line = new Border { Height = 1 };
+ line.SetResourceReference(Border.BackgroundProperty, "ControlStrokeBrush");
+ ImportList.Children.Add(line);
+ }
+ ImportList.Children.Add(box);
+ }
+ }
+
+ private List SelectedImports() =>
+ ImportList.Children.OfType()
+ .Where(c => c.IsChecked == true && c.Tag is FoundLauncher)
+ .Select(c => (FoundLauncher)c.Tag)
+ .ToList();
+
+ private void ChangeDir_Click(object sender, RoutedEventArgs e)
+ {
+ using var dlg = new System.Windows.Forms.FolderBrowserDialog
+ {
+ Description = "Installationsordner wählen",
+ SelectedPath = Directory.Exists(DirBox.Text) ? DirBox.Text : Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
+ ShowNewFolderButton = true,
+ };
+ if (dlg.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
+ var chosen = dlg.SelectedPath;
+ // wie bei üblichen Installern: Unterordner "AeroMC" anhängen
+ DirBox.Text = Path.GetFileName(chosen.TrimEnd('\\')).Equals("AeroMC", StringComparison.OrdinalIgnoreCase)
+ ? chosen : Path.Combine(chosen, "AeroMC");
+ }
+
+ // ---------- Installation ----------
+
+ private async Task RunInstall(string dir, bool desktop, bool update)
+ {
+ _busy = true;
+ if (!update) ShowPage(PageNumProgress);
+ SetButtons(false);
+ var progress = new Progress<(double Value, string Text)>(p => SetProgress(p.Value, p.Text));
+ try
+ {
+ await Task.Run(() => Installer.Install(dir, desktop, progress, waitForExit: update));
+ _installedExe = Path.Combine(dir, Installer.ExeName);
+ _done = true;
+
+ if (update)
+ {
+ ShowSuccess("Update abgeschlossen", $"AeroMC {Installer.Version} wird gestartet …");
+ StartApp();
+ _busy = false;
+ var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1.5) };
+ timer.Tick += (_, _) => { timer.Stop(); Close(); };
+ timer.Start();
+ return;
+ }
+
+ // ausgewählte Launcher für den ersten Start vormerken (Fehler hier sollen die Installation nicht kippen)
+ var selected = SelectedImports();
+ try { LauncherImport.WritePending(selected); } catch { selected = []; }
+
+ ShowSuccess("Alles bereit!", "AeroMC ist installiert. Du findest es im Startmenü" + (desktop ? " und auf dem Desktop." : "."));
+ if (selected.Count > 0)
+ ProgressText.Text += $" Beim ersten Start bietet AeroMC dir die Instanzen aus {string.Join(" und ", selected.Select(f => f.Name))} zum Übernehmen an.";
+ DonePanel.Visibility = Visibility.Visible;
+ ShowPage(PageNumProgress);
+ }
+ catch (Exception ex)
+ {
+ ProgressTitle.Text = update ? "Update fehlgeschlagen" : "Installation fehlgeschlagen";
+ ProgressBarPanel.Visibility = Visibility.Collapsed;
+ ProgressText.Text = ex.Message;
+ ProgressText.Foreground = (Brush)FindResource("DangerBrush");
+ NextButton.Content = "Schließen";
+ _installedExe = null;
+ }
+ _busy = false;
+ NextButton.IsEnabled = true;
+ CloseButton.IsEnabled = true;
+ BackButton.Visibility = Visibility.Hidden;
+ CancelButton.Visibility = Visibility.Collapsed;
+ }
+
+ /// Fortschritt ausblenden und den Haken mit kurzem "Aufploppen" zeigen.
+ private void ShowSuccess(string title, string text)
+ {
+ ProgressBarPanel.Visibility = Visibility.Collapsed;
+ ProgressTitle.Text = title;
+ ProgressText.Text = text;
+ SuccessIcon.Visibility = Visibility.Visible;
+ var pop = new DoubleAnimation(0.4, 1, TimeSpan.FromMilliseconds(420)) { EasingFunction = new BackEase { EasingMode = EasingMode.EaseOut, Amplitude = 0.5 } };
+ SuccessScale.BeginAnimation(ScaleTransform.ScaleXProperty, pop);
+ SuccessScale.BeginAnimation(ScaleTransform.ScaleYProperty, pop);
+ SuccessIcon.BeginAnimation(OpacityProperty, new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(200)));
+ }
+
+ private void StartApp()
+ {
+ if (_installedExe is null || !File.Exists(_installedExe)) return;
+ try
+ {
+ Process.Start(new ProcessStartInfo(_installedExe)
+ {
+ UseShellExecute = true,
+ WorkingDirectory = Path.GetDirectoryName(_installedExe)!,
+ });
+ }
+ catch { }
+ }
+
+ // ---------- Deinstallation ----------
+
+ private async void LoadDataInfo()
+ {
+ var root = Installer.DataDir;
+ var custom = Installer.CustomInstancesDir;
+ var customNote = custom is null ? "" : $" Instanzen in deinem eigenen Ordner {custom} werden nie angefasst.";
+ if (!Directory.Exists(root))
+ {
+ DataInfo.Text = "Es wurden keine Launcher-Daten gefunden." + customNote;
+ RemoveDataBox.IsEnabled = false;
+ return;
+ }
+ DataInfo.Text = $"Sie liegen in {root}. Größe wird berechnet …";
+ var size = await Task.Run(Installer.DataSize);
+ DataInfo.Text = $"Sie liegen in {root} ({Installer.FormatSize(size)}) und stehen wieder bereit, falls du AeroMC später neu installierst." + customNote;
+ }
+
+ private void RemoveDataBox_Click(object sender, RoutedEventArgs e) =>
+ RemoveDataWarning.Visibility = RemoveDataBox.IsChecked == true ? Visibility.Visible : Visibility.Collapsed;
+
+ private async Task RunUninstall()
+ {
+ _busy = true;
+ bool removeData = RemoveDataBox.IsChecked == true;
+ ShowOnly(PageProgress);
+ ProgressTitle.Text = "AeroMC wird entfernt …";
+ LaunchBox.Visibility = Visibility.Collapsed;
+ SetButtons(false);
+ var progress = new Progress<(double Value, string Text)>(p => SetProgress(p.Value, p.Text));
+ try
+ {
+ await Task.Run(() => Installer.Uninstall(removeData, progress));
+ ShowSuccess("AeroMC wurde entfernt", removeData
+ ? "AeroMC, deine Instanzen, Konten und Einstellungen wurden entfernt (die Daten liegen im Papierkorb)."
+ : "Deine Instanzen und Einstellungen liegen weiterhin in " + Installer.DataDir + " – falls du AeroMC später wieder installierst.");
+ }
+ catch (Exception ex)
+ {
+ ProgressTitle.Text = "Deinstallation fehlgeschlagen";
+ ProgressBarPanel.Visibility = Visibility.Collapsed;
+ ProgressText.Text = ex.Message;
+ }
+ _done = true;
+ _busy = false;
+ CloseButton.IsEnabled = true;
+ NextButton.Content = "Schließen";
+ NextButton.IsEnabled = true;
+ CancelButton.Visibility = Visibility.Collapsed;
+ }
+
+ // ---------- Helfer ----------
+
+ private void SetButtons(bool enabled)
+ {
+ NextButton.IsEnabled = enabled;
+ BackButton.IsEnabled = enabled;
+ CancelButton.IsEnabled = enabled;
+ CloseButton.IsEnabled = enabled;
+ }
+
+ private void SetProgress(double value, string text)
+ {
+ if (_done) return;
+ ProgressText.Text = text;
+ PercentText.Text = $"{(int)Math.Round(value * 100)} %";
+ _progress = value;
+ AnimateProgress();
+ }
+
+ private double _progress;
+
+ private void AnimateProgress()
+ {
+ var target = Math.Max(0, ProgressTrack.ActualWidth * _progress);
+ ProgressFill.BeginAnimation(WidthProperty,
+ new DoubleAnimation(target, TimeSpan.FromMilliseconds(250)) { EasingFunction = new CubicEase() });
+ }
+
+ // Kommt der erste Wert, bevor die Seite fertig angeordnet ist (Breite 0), nachträglich richtig setzen
+ private void ProgressTrack_SizeChanged(object sender, SizeChangedEventArgs e) => AnimateProgress();
+
+ private static bool IsFullPath(string p) =>
+ p.Length >= 3 && char.IsLetter(p[0]) && p[1] == ':' && (p[2] == '\\' || p[2] == '/');
+
+ private void Minimize_Click(object sender, RoutedEventArgs e) => WindowState = WindowState.Minimized;
+
+ private void Cancel_Click(object sender, RoutedEventArgs e)
+ {
+ if (_busy) return;
+ if (!_done && _mode == SetupMode.Install && _page > 0 &&
+ MessageBox.Show(this, "Installation wirklich abbrechen?", "AeroMC Setup", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
+ return;
+ Close();
+ }
+
+ protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
+ {
+ if (_busy) e.Cancel = true; // während der Installation nicht schließen
+ base.OnClosing(e);
+ }
+}
diff --git a/installer/Payload.cs b/installer/Payload.cs
new file mode 100644
index 0000000..a860b7f
--- /dev/null
+++ b/installer/Payload.cs
@@ -0,0 +1,106 @@
+using System.IO;
+using System.IO.Compression;
+using System.Text;
+
+namespace AeroMCSetup;
+
+///
+/// Die App liegt als ZIP hinten an der Setup-.exe angehängt:
+/// [Setup.exe][ZIP][8 Byte: ZIP-Länge][8 Byte: "AEROMCPK"]
+/// Windows ignoriert angehängte Daten beim Starten einer .exe.
+///
+public static class Payload
+{
+ private static readonly byte[] Magic = Encoding.ASCII.GetBytes("AEROMCPK");
+ private const int FooterSize = 16;
+
+ private static (long Offset, long Length)? _info;
+ private static bool _checked;
+
+ /// Position und Länge des ZIPs in dieser .exe, oder null (z. B. beim Deinstallationsprogramm).
+ public static (long Offset, long Length)? Info
+ {
+ get
+ {
+ if (_checked) return _info;
+ _checked = true;
+ try
+ {
+ using var f = File.OpenRead(Installer.SelfPath);
+ if (f.Length < FooterSize) return null;
+ f.Seek(-FooterSize, SeekOrigin.End);
+ var footer = new byte[FooterSize];
+ if (f.Read(footer, 0, FooterSize) != FooterSize) return null;
+ for (int i = 0; i < Magic.Length; i++)
+ if (footer[8 + i] != Magic[i]) return null;
+ long length = BitConverter.ToInt64(footer, 0);
+ long offset = f.Length - FooterSize - length;
+ if (length <= 0 || offset <= 0) return null;
+ _info = (offset, length);
+ }
+ catch { _info = null; }
+ return _info;
+ }
+ }
+
+ public static bool Exists => Info is not null;
+
+ /// Länge des eigentlichen Setup-Programms ohne Anhang.
+ public static long StubLength => Info?.Offset ?? new FileInfo(Installer.SelfPath).Length;
+
+ public static ZipArchive OpenArchive()
+ {
+ var info = Info ?? throw new InvalidOperationException("Die Installationsdaten fehlen in dieser Datei. Bitte AeroMC-Setup.exe neu herunterladen.");
+ var file = File.OpenRead(Installer.SelfPath);
+ return new ZipArchive(new SubStream(file, info.Offset, info.Length), ZipArchiveMode.Read, leaveOpen: false);
+ }
+
+ /// Nur-Lese-Ausschnitt einer Datei, damit ZipArchive den Anhang wie eine eigene Datei sieht.
+ private sealed class SubStream(Stream inner, long start, long length) : Stream
+ {
+ private long _pos;
+
+ public override bool CanRead => true;
+ public override bool CanSeek => true;
+ public override bool CanWrite => false;
+ public override long Length => length;
+
+ public override long Position
+ {
+ get => _pos;
+ set => _pos = Math.Max(0, Math.Min(value, length));
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ long left = length - _pos;
+ if (left <= 0) return 0;
+ if (count > left) count = (int)left;
+ inner.Position = start + _pos;
+ int n = inner.Read(buffer, offset, count);
+ _pos += n;
+ return n;
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ Position = origin switch
+ {
+ SeekOrigin.Begin => offset,
+ SeekOrigin.Current => _pos + offset,
+ _ => length + offset,
+ };
+ return _pos;
+ }
+
+ public override void Flush() { }
+ public override void SetLength(long value) => throw new NotSupportedException();
+ public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing) inner.Dispose();
+ base.Dispose(disposing);
+ }
+ }
+}
diff --git a/installer/Shortcut.cs b/installer/Shortcut.cs
new file mode 100644
index 0000000..f174b79
--- /dev/null
+++ b/installer/Shortcut.cs
@@ -0,0 +1,110 @@
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+
+namespace AeroMCSetup;
+
+///
+/// Verknüpfungen (.lnk) über die Shell-Schnittstellen – inklusive AppUserModelID, damit
+/// Taskleiste und Windows-Benachrichtigungen AeroMC wie bisher zuordnen (wie beim alten NSIS-Setup).
+///
+public static class Shortcut
+{
+ public static void Create(string link, string target, string description, string appUserModelId)
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(link)!);
+ var shellLink = (IShellLinkW)new CShellLink();
+ try
+ {
+ shellLink.SetPath(target);
+ shellLink.SetWorkingDirectory(Path.GetDirectoryName(target)!);
+ shellLink.SetIconLocation(target, 0);
+ shellLink.SetDescription(description);
+
+ var store = (IPropertyStore)shellLink;
+ var key = new PropertyKey(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 5); // PKEY_AppUserModel_ID
+ var value = new PropVariant { vt = 31 /* VT_LPWSTR */, p = Marshal.StringToCoTaskMemUni(appUserModelId) };
+ try
+ {
+ store.SetValue(ref key, ref value);
+ store.Commit();
+ }
+ finally { Marshal.FreeCoTaskMem(value.p); }
+
+ ((IPersistFile)shellLink).Save(link, true);
+ }
+ finally { Marshal.ReleaseComObject(shellLink); }
+ }
+
+ /// Ziel einer vorhandenen Verknüpfung, oder null.
+ public static string? Target(string link)
+ {
+ if (!File.Exists(link)) return null;
+ var shellLink = (IShellLinkW)new CShellLink();
+ try
+ {
+ ((IPersistFile)shellLink).Load(link, 0);
+ var sb = new StringBuilder(1024);
+ shellLink.GetPath(sb, sb.Capacity, IntPtr.Zero, 0);
+ return sb.ToString();
+ }
+ catch { return null; }
+ finally { Marshal.ReleaseComObject(shellLink); }
+ }
+
+ // ---------- COM ----------
+
+ [ComImport, Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, IntPtr pfd, uint fFlags);
+ void GetIDList(out IntPtr ppidl);
+ void SetIDList(IntPtr pidl);
+ void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
+ void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
+ void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
+ void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ void GetHotkey(out short pwHotkey);
+ void SetHotkey(short wHotkey);
+ void GetShowCmd(out int piShowCmd);
+ void SetShowCmd(int iShowCmd);
+ void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
+ void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved);
+ void Resolve(IntPtr hwnd, uint fFlags);
+ void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ void GetCount(out uint cProps);
+ void GetAt(uint iProp, out PropertyKey pkey);
+ void GetValue(ref PropertyKey key, out PropVariant pv);
+ void SetValue(ref PropertyKey key, ref PropVariant pv);
+ void Commit();
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey(Guid fmtid, uint pid)
+ {
+ public Guid fmtid = fmtid;
+ public uint pid = pid;
+ }
+
+ // PROPVARIANT: 16 Byte (32 Bit) bzw. 24 Byte (64 Bit)
+ [StructLayout(LayoutKind.Sequential)]
+ private struct PropVariant
+ {
+ public ushort vt;
+ public ushort r1, r2, r3;
+ public IntPtr p;
+ public IntPtr p2;
+ }
+}
diff --git a/installer/Themes/Colors.Dark.xaml b/installer/Themes/Colors.Dark.xaml
new file mode 100644
index 0000000..f6250a8
--- /dev/null
+++ b/installer/Themes/Colors.Dark.xaml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #000000
+
diff --git a/installer/Themes/Colors.Light.xaml b/installer/Themes/Colors.Light.xaml
new file mode 100644
index 0000000..e311b00
--- /dev/null
+++ b/installer/Themes/Colors.Light.xaml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #000000
+
diff --git a/installer/Themes/Controls.xaml b/installer/Themes/Controls.xaml
new file mode 100644
index 0000000..9d6865a
--- /dev/null
+++ b/installer/Themes/Controls.xaml
@@ -0,0 +1,651 @@
+
+
+
+ Segoe UI Variable Text, Segoe UI
+ Segoe UI Variable Display, Segoe UI
+ Segoe Fluent Icons, Segoe MDL2 Assets
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/app.manifest b/installer/app.manifest
new file mode 100644
index 0000000..98f7b62
--- /dev/null
+++ b/installer/app.manifest
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true/pm
+ PerMonitorV2
+
+
+
diff --git a/installer/obj/AeroMCSetup.csproj.nuget.dgspec.json b/installer/obj/AeroMCSetup.csproj.nuget.dgspec.json
new file mode 100644
index 0000000..b56f175
--- /dev/null
+++ b/installer/obj/AeroMCSetup.csproj.nuget.dgspec.json
@@ -0,0 +1,59 @@
+{
+ "format": 1,
+ "restore": {
+ "C:\\Users\\Viper\\Desktop\\AeroMC-Launcher\\installer\\AeroMCSetup.csproj": {}
+ },
+ "projects": {
+ "C:\\Users\\Viper\\Desktop\\AeroMC-Launcher\\installer\\AeroMCSetup.csproj": {
+ "version": "1.1.4",
+ "restore": {
+ "projectUniqueName": "C:\\Users\\Viper\\Desktop\\AeroMC-Launcher\\installer\\AeroMCSetup.csproj",
+ "projectName": "AeroMC-Setup",
+ "projectPath": "C:\\Users\\Viper\\Desktop\\AeroMC-Launcher\\installer\\AeroMCSetup.csproj",
+ "packagesPath": "C:\\Users\\Viper\\.nuget\\packages\\",
+ "outputPath": "C:\\Users\\Viper\\Desktop\\AeroMC-Launcher\\installer\\obj\\",
+ "projectStyle": "PackageReference",
+ "configFilePaths": [
+ "C:\\Users\\Viper\\AppData\\Roaming\\NuGet\\NuGet.Config"
+ ],
+ "originalTargetFrameworks": [
+ "net48"
+ ],
+ "sources": {
+ "https://api.nuget.org/v3/index.json": {}
+ },
+ "frameworks": {
+ "net48": {
+ "targetAlias": "net48",
+ "projectReferences": {}
+ }
+ },
+ "warningProperties": {
+ "warnAsError": [
+ "NU1605"
+ ]
+ },
+ "restoreAuditProperties": {
+ "enableAudit": "true",
+ "auditLevel": "low",
+ "auditMode": "direct"
+ },
+ "SdkAnalysisLevel": "10.0.100"
+ },
+ "frameworks": {
+ "net48": {
+ "targetAlias": "net48",
+ "dependencies": {
+ "Microsoft.NETFramework.ReferenceAssemblies": {
+ "suppressParent": "All",
+ "target": "Package",
+ "version": "[1.0.3, )",
+ "autoReferenced": true
+ }
+ },
+ "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.112\\RuntimeIdentifierGraph.json"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/installer/obj/AeroMCSetup.csproj.nuget.g.props b/installer/obj/AeroMCSetup.csproj.nuget.g.props
new file mode 100644
index 0000000..5db7e09
--- /dev/null
+++ b/installer/obj/AeroMCSetup.csproj.nuget.g.props
@@ -0,0 +1,15 @@
+
+
+
+ True
+ NuGet
+ $(MSBuildThisFileDirectory)project.assets.json
+ $(UserProfile)\.nuget\packages\
+ C:\Users\Viper\.nuget\packages\
+ PackageReference
+ 7.0.0
+
+
+
+
+
\ No newline at end of file
diff --git a/installer/obj/AeroMCSetup.csproj.nuget.g.targets b/installer/obj/AeroMCSetup.csproj.nuget.g.targets
new file mode 100644
index 0000000..83f7de5
--- /dev/null
+++ b/installer/obj/AeroMCSetup.csproj.nuget.g.targets
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/installer/obj/Release/net48/.NETFramework,Version=v4.8.AssemblyAttributes.cs b/installer/obj/Release/net48/.NETFramework,Version=v4.8.AssemblyAttributes.cs
new file mode 100644
index 0000000..3cf0af3
--- /dev/null
+++ b/installer/obj/Release/net48/.NETFramework,Version=v4.8.AssemblyAttributes.cs
@@ -0,0 +1,4 @@
+//
+using System;
+using System.Reflection;
+[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
diff --git a/installer/obj/Release/net48/AeroMC-Setup.exe b/installer/obj/Release/net48/AeroMC-Setup.exe
new file mode 100644
index 0000000..556a5ce
Binary files /dev/null and b/installer/obj/Release/net48/AeroMC-Setup.exe differ
diff --git a/installer/obj/Release/net48/AeroMC-Setup.exe.withSupportedRuntime.config b/installer/obj/Release/net48/AeroMC-Setup.exe.withSupportedRuntime.config
new file mode 100644
index 0000000..ef94b7c
--- /dev/null
+++ b/installer/obj/Release/net48/AeroMC-Setup.exe.withSupportedRuntime.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/installer/obj/Release/net48/AeroMC-Setup.g.resources b/installer/obj/Release/net48/AeroMC-Setup.g.resources
new file mode 100644
index 0000000..1a7bfd5
Binary files /dev/null and b/installer/obj/Release/net48/AeroMC-Setup.g.resources differ
diff --git a/installer/obj/Release/net48/AeroMC-Setup_MarkupCompile.cache b/installer/obj/Release/net48/AeroMC-Setup_MarkupCompile.cache
new file mode 100644
index 0000000..8526486
--- /dev/null
+++ b/installer/obj/Release/net48/AeroMC-Setup_MarkupCompile.cache
@@ -0,0 +1,20 @@
+AeroMC-Setup
+
+
+winexe
+C#
+.cs
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\
+AeroMCSetup
+none
+false
+TRACE;RELEASE;NETFRAMEWORK;NET48;NET30_OR_GREATER;NET35_OR_GREATER;NET40_OR_GREATER;NET45_OR_GREATER;NET451_OR_GREATER;NET452_OR_GREATER;NET46_OR_GREATER;NET461_OR_GREATER;NET462_OR_GREATER;NET47_OR_GREATER;NET471_OR_GREATER;NET472_OR_GREATER;NET48_OR_GREATER
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\App.xaml
+41549299691
+
+7-621693760
+251587687494
+MainWindow.xaml;Themes\Colors.Dark.xaml;Themes\Colors.Light.xaml;Themes\Controls.xaml;
+
+False
+
diff --git a/installer/obj/Release/net48/AeroMCSetup.AssemblyInfo.cs b/installer/obj/Release/net48/AeroMCSetup.AssemblyInfo.cs
new file mode 100644
index 0000000..79dcd07
--- /dev/null
+++ b/installer/obj/Release/net48/AeroMCSetup.AssemblyInfo.cs
@@ -0,0 +1,25 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+using System;
+using System.Reflection;
+
+[assembly: System.Reflection.AssemblyCompanyAttribute("M_Viper")]
+[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
+[assembly: System.Reflection.AssemblyCopyrightAttribute("Copyright (c) M_Viper. Alle Rechte vorbehalten.")]
+[assembly: System.Reflection.AssemblyDescriptionAttribute("Installiert AeroMC")]
+[assembly: System.Reflection.AssemblyFileVersionAttribute("1.1.4.0")]
+[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.1.4")]
+[assembly: System.Reflection.AssemblyProductAttribute("AeroMC Setup")]
+[assembly: System.Reflection.AssemblyTitleAttribute("AeroMC Setup")]
+[assembly: System.Reflection.AssemblyVersionAttribute("1.1.4.0")]
+[assembly: System.Resources.NeutralResourcesLanguageAttribute("de-DE")]
+
+// Von der MSBuild WriteCodeFragment-Klasse generiert.
+
diff --git a/installer/obj/Release/net48/AeroMCSetup.AssemblyInfoInputs.cache b/installer/obj/Release/net48/AeroMCSetup.AssemblyInfoInputs.cache
new file mode 100644
index 0000000..b40ee98
--- /dev/null
+++ b/installer/obj/Release/net48/AeroMCSetup.AssemblyInfoInputs.cache
@@ -0,0 +1 @@
+bf2163e2bc9cc6ae9fd7bde3e12e19f0edbf97f159f3e572c7d202d23603f380
diff --git a/installer/obj/Release/net48/AeroMCSetup.GeneratedMSBuildEditorConfig.editorconfig b/installer/obj/Release/net48/AeroMCSetup.GeneratedMSBuildEditorConfig.editorconfig
new file mode 100644
index 0000000..b4b7844
--- /dev/null
+++ b/installer/obj/Release/net48/AeroMCSetup.GeneratedMSBuildEditorConfig.editorconfig
@@ -0,0 +1,14 @@
+is_global = true
+build_property.ApplicationManifest = app.manifest
+build_property.StartupObject =
+build_property.ApplicationDefaultFont =
+build_property.ApplicationHighDpiMode =
+build_property.ApplicationUseCompatibleTextRendering =
+build_property.ApplicationVisualStyles =
+build_property.RootNamespace = AeroMCSetup
+build_property.ProjectDir = C:\Users\Viper\Desktop\AeroMC-Launcher\installer\
+build_property.EnableComHosting =
+build_property.EnableGeneratedComInterfaceComImportInterop =
+build_property.CsWinRTUseWindowsUIXamlProjections = false
+build_property.EffectiveAnalysisLevelStyle =
+build_property.EnableCodeStyleSeverity =
diff --git a/installer/obj/Release/net48/AeroMCSetup.GlobalUsings.g.cs b/installer/obj/Release/net48/AeroMCSetup.GlobalUsings.g.cs
new file mode 100644
index 0000000..4a15929
--- /dev/null
+++ b/installer/obj/Release/net48/AeroMCSetup.GlobalUsings.g.cs
@@ -0,0 +1,6 @@
+//
+global using System;
+global using System.Collections.Generic;
+global using System.Linq;
+global using System.Threading;
+global using System.Threading.Tasks;
diff --git a/installer/obj/Release/net48/AeroMCSetup.assets.cache b/installer/obj/Release/net48/AeroMCSetup.assets.cache
new file mode 100644
index 0000000..d4e870f
Binary files /dev/null and b/installer/obj/Release/net48/AeroMCSetup.assets.cache differ
diff --git a/installer/obj/Release/net48/AeroMCSetup.csproj.AssemblyReference.cache b/installer/obj/Release/net48/AeroMCSetup.csproj.AssemblyReference.cache
new file mode 100644
index 0000000..9f9724f
Binary files /dev/null and b/installer/obj/Release/net48/AeroMCSetup.csproj.AssemblyReference.cache differ
diff --git a/installer/obj/Release/net48/AeroMCSetup.csproj.CoreCompileInputs.cache b/installer/obj/Release/net48/AeroMCSetup.csproj.CoreCompileInputs.cache
new file mode 100644
index 0000000..6a2511a
--- /dev/null
+++ b/installer/obj/Release/net48/AeroMCSetup.csproj.CoreCompileInputs.cache
@@ -0,0 +1 @@
+75ed8898b0d415db8840bc8e86cbe862583b62e51d945f302629778ca05c0e99
diff --git a/installer/obj/Release/net48/AeroMCSetup.csproj.FileListAbsolute.txt b/installer/obj/Release/net48/AeroMCSetup.csproj.FileListAbsolute.txt
new file mode 100644
index 0000000..017819b
--- /dev/null
+++ b/installer/obj/Release/net48/AeroMCSetup.csproj.FileListAbsolute.txt
@@ -0,0 +1,26 @@
+C:\Users\Viper\Desktop\AeroMC-Launcher\dist-setup-test\AeroMC-Setup.exe.config
+C:\Users\Viper\Desktop\AeroMC-Launcher\dist-setup-test\AeroMC-Setup.exe
+C:\Users\Viper\Desktop\AeroMC-Launcher\dist-setup-test\AeroMC-Setup.pdb
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\AeroMCSetup.csproj.AssemblyReference.cache
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\MainWindow.baml
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\Themes\Colors.Dark.baml
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\Themes\Colors.Light.baml
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\Themes\Controls.baml
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\App.baml
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\MainWindow.g.cs
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\App.g.cs
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\AeroMC-Setup_MarkupCompile.cache
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\AeroMC-Setup.g.resources
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\AeroMCSetup.GeneratedMSBuildEditorConfig.editorconfig
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\AeroMCSetup.AssemblyInfoInputs.cache
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\AeroMCSetup.AssemblyInfo.cs
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\AeroMCSetup.csproj.CoreCompileInputs.cache
+C:\Users\Viper\Desktop\AeroMC-Launcher\installer\obj\Release\net48\AeroMC-Setup.exe
+C:\Users\Viper\Desktop\AeroMC-Launcher\dist\.setup\stub\AeroMC-Setup.exe.config
+C:\Users\Viper\Desktop\AeroMC-Launcher\dist\.setup\stub\AeroMC-Setup.exe
+C:\Users\Viper\AppData\Local\Temp\claude\C--Users-Viper-Desktop-AeroMC-Launcher\1859f458-aac9-4e4b-be87-3e40160ebab1\scratchpad\stubtest\AeroMC-Setup.exe.config
+C:\Users\Viper\AppData\Local\Temp\claude\C--Users-Viper-Desktop-AeroMC-Launcher\1859f458-aac9-4e4b-be87-3e40160ebab1\scratchpad\stubtest\AeroMC-Setup.exe
+C:\Users\Viper\AppData\Local\Temp\claude\C--Users-Viper-Desktop-AeroMC-Launcher\1859f458-aac9-4e4b-be87-3e40160ebab1\scratchpad\stubtest\AeroMC-Setup.pdb
+C:\Users\Viper\AppData\Local\Temp\claude\C--Users-Viper-Desktop-AeroMC-Launcher\1859f458-aac9-4e4b-be87-3e40160ebab1\scratchpad\stubtest2\AeroMC-Setup.exe.config
+C:\Users\Viper\AppData\Local\Temp\claude\C--Users-Viper-Desktop-AeroMC-Launcher\1859f458-aac9-4e4b-be87-3e40160ebab1\scratchpad\stubtest2\AeroMC-Setup.exe
+C:\Users\Viper\AppData\Local\Temp\claude\C--Users-Viper-Desktop-AeroMC-Launcher\1859f458-aac9-4e4b-be87-3e40160ebab1\scratchpad\stubtest2\AeroMC-Setup.pdb
diff --git a/installer/obj/Release/net48/App.baml b/installer/obj/Release/net48/App.baml
new file mode 100644
index 0000000..feb297a
Binary files /dev/null and b/installer/obj/Release/net48/App.baml differ
diff --git a/installer/obj/Release/net48/App.g.cs b/installer/obj/Release/net48/App.g.cs
new file mode 100644
index 0000000..a4913e0
--- /dev/null
+++ b/installer/obj/Release/net48/App.g.cs
@@ -0,0 +1,77 @@
+#pragma checksum "..\..\..\App.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "85CCB5F529C7F3695DF076BCDBCCA84D8F4ED0DE"
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+using System;
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Automation;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Controls.Ribbon;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Forms.Integration;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Markup;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Media.Effects;
+using System.Windows.Media.Imaging;
+using System.Windows.Media.Media3D;
+using System.Windows.Media.TextFormatting;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using System.Windows.Shell;
+
+
+namespace AeroMCSetup {
+
+
+ ///
+ /// App
+ ///
+ public partial class App : System.Windows.Application {
+
+ private bool _contentLoaded;
+
+ ///
+ /// InitializeComponent
+ ///
+ [System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "10.0.12.0")]
+ public void InitializeComponent() {
+ if (_contentLoaded) {
+ return;
+ }
+ _contentLoaded = true;
+ System.Uri resourceLocater = new System.Uri("/AeroMC-Setup;component/app.xaml", System.UriKind.Relative);
+
+ #line 1 "..\..\..\App.xaml"
+ System.Windows.Application.LoadComponent(this, resourceLocater);
+
+ #line default
+ #line hidden
+ }
+
+ ///
+ /// Application Entry Point.
+ ///
+ [System.STAThreadAttribute()]
+ [System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "10.0.12.0")]
+ public static void Main() {
+ AeroMCSetup.App app = new AeroMCSetup.App();
+ app.InitializeComponent();
+ app.Run();
+ }
+ }
+}
+
diff --git a/installer/obj/Release/net48/MainWindow.baml b/installer/obj/Release/net48/MainWindow.baml
new file mode 100644
index 0000000..8c0ec30
Binary files /dev/null and b/installer/obj/Release/net48/MainWindow.baml differ
diff --git a/installer/obj/Release/net48/MainWindow.g.cs b/installer/obj/Release/net48/MainWindow.g.cs
new file mode 100644
index 0000000..0f64b3f
--- /dev/null
+++ b/installer/obj/Release/net48/MainWindow.g.cs
@@ -0,0 +1,753 @@
+#pragma checksum "..\..\..\MainWindow.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "880600C0B188AB084F9AD1662CDB9BED2AA222A8"
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+using System;
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Automation;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Controls.Ribbon;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Forms.Integration;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Markup;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Media.Effects;
+using System.Windows.Media.Imaging;
+using System.Windows.Media.Media3D;
+using System.Windows.Media.TextFormatting;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using System.Windows.Shell;
+
+
+namespace AeroMCSetup {
+
+
+ ///
+ /// MainWindow
+ ///
+ public partial class MainWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector {
+
+
+ #line 140 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock VersionText;
+
+ #line default
+ #line hidden
+
+
+ #line 142 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.StackPanel Steps;
+
+ #line default
+ #line hidden
+
+
+ #line 144 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border Dot0;
+
+ #line default
+ #line hidden
+
+
+ #line 144 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock Num0;
+
+ #line default
+ #line hidden
+
+
+ #line 145 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock Label0;
+
+ #line default
+ #line hidden
+
+
+ #line 147 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border Line0;
+
+ #line default
+ #line hidden
+
+
+ #line 149 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border Dot1;
+
+ #line default
+ #line hidden
+
+
+ #line 149 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock Num1;
+
+ #line default
+ #line hidden
+
+
+ #line 150 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock Label1;
+
+ #line default
+ #line hidden
+
+
+ #line 152 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border Line1;
+
+ #line default
+ #line hidden
+
+
+ #line 154 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border Dot2;
+
+ #line default
+ #line hidden
+
+
+ #line 154 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock Num2;
+
+ #line default
+ #line hidden
+
+
+ #line 155 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock Label2;
+
+ #line default
+ #line hidden
+
+
+ #line 157 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border Line2;
+
+ #line default
+ #line hidden
+
+
+ #line 159 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.StackPanel ImportStepRow;
+
+ #line default
+ #line hidden
+
+
+ #line 160 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border Dot3;
+
+ #line default
+ #line hidden
+
+
+ #line 160 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock Num3;
+
+ #line default
+ #line hidden
+
+
+ #line 161 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock Label3;
+
+ #line default
+ #line hidden
+
+
+ #line 163 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border Line3;
+
+ #line default
+ #line hidden
+
+
+ #line 165 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border Dot4;
+
+ #line default
+ #line hidden
+
+
+ #line 165 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock Num4;
+
+ #line default
+ #line hidden
+
+
+ #line 166 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock Label4;
+
+ #line default
+ #line hidden
+
+
+ #line 179 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock WindowTitle;
+
+ #line default
+ #line hidden
+
+
+ #line 185 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Button CloseButton;
+
+ #line default
+ #line hidden
+
+
+ #line 193 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.StackPanel PageWelcome;
+
+ #line default
+ #line hidden
+
+
+ #line 240 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border UpdateHint;
+
+ #line default
+ #line hidden
+
+
+ #line 245 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock UpdateHintText;
+
+ #line default
+ #line hidden
+
+
+ #line 248 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border RunningHint;
+
+ #line default
+ #line hidden
+
+
+ #line 260 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.DockPanel PageLicense;
+
+ #line default
+ #line hidden
+
+
+ #line 264 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.CheckBox AcceptLicense;
+
+ #line default
+ #line hidden
+
+
+ #line 270 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock LicenseText;
+
+ #line default
+ #line hidden
+
+
+ #line 277 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.StackPanel PageOptions;
+
+ #line default
+ #line hidden
+
+
+ #line 286 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBox DirBox;
+
+ #line default
+ #line hidden
+
+
+ #line 295 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.CheckBox DesktopLinkBox;
+
+ #line default
+ #line hidden
+
+
+ #line 296 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.CheckBox StartMenuBox;
+
+ #line default
+ #line hidden
+
+
+ #line 302 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.StackPanel PageImport;
+
+ #line default
+ #line hidden
+
+
+ #line 307 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.StackPanel ImportList;
+
+ #line default
+ #line hidden
+
+
+ #line 314 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.StackPanel PageProgress;
+
+ #line default
+ #line hidden
+
+
+ #line 315 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border SuccessIcon;
+
+ #line default
+ #line hidden
+
+
+ #line 317 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Media.ScaleTransform SuccessScale;
+
+ #line default
+ #line hidden
+
+
+ #line 322 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock ProgressTitle;
+
+ #line default
+ #line hidden
+
+
+ #line 324 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.StackPanel ProgressBarPanel;
+
+ #line default
+ #line hidden
+
+
+ #line 325 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock PercentText;
+
+ #line default
+ #line hidden
+
+
+ #line 327 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border ProgressTrack;
+
+ #line default
+ #line hidden
+
+
+ #line 328 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Border ProgressFill;
+
+ #line default
+ #line hidden
+
+
+ #line 331 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock ProgressText;
+
+ #line default
+ #line hidden
+
+
+ #line 333 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.StackPanel DonePanel;
+
+ #line default
+ #line hidden
+
+
+ #line 334 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.CheckBox LaunchBox;
+
+ #line default
+ #line hidden
+
+
+ #line 339 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.StackPanel PageUninstall;
+
+ #line default
+ #line hidden
+
+
+ #line 350 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock DataInfo;
+
+ #line default
+ #line hidden
+
+
+ #line 351 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.CheckBox RemoveDataBox;
+
+ #line default
+ #line hidden
+
+
+ #line 353 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.TextBlock RemoveDataWarning;
+
+ #line default
+ #line hidden
+
+
+ #line 363 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Button BackButton;
+
+ #line default
+ #line hidden
+
+
+ #line 364 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Button NextButton;
+
+ #line default
+ #line hidden
+
+
+ #line 365 "..\..\..\MainWindow.xaml"
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
+ internal System.Windows.Controls.Button CancelButton;
+
+ #line default
+ #line hidden
+
+ private bool _contentLoaded;
+
+ ///
+ /// InitializeComponent
+ ///
+ [System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "10.0.12.0")]
+ public void InitializeComponent() {
+ if (_contentLoaded) {
+ return;
+ }
+ _contentLoaded = true;
+ System.Uri resourceLocater = new System.Uri("/AeroMC-Setup;component/mainwindow.xaml", System.UriKind.Relative);
+
+ #line 1 "..\..\..\MainWindow.xaml"
+ System.Windows.Application.LoadComponent(this, resourceLocater);
+
+ #line default
+ #line hidden
+ }
+
+ [System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "10.0.12.0")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
+ void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
+ switch (connectionId)
+ {
+ case 1:
+ this.VersionText = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 2:
+ this.Steps = ((System.Windows.Controls.StackPanel)(target));
+ return;
+ case 3:
+ this.Dot0 = ((System.Windows.Controls.Border)(target));
+ return;
+ case 4:
+ this.Num0 = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 5:
+ this.Label0 = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 6:
+ this.Line0 = ((System.Windows.Controls.Border)(target));
+ return;
+ case 7:
+ this.Dot1 = ((System.Windows.Controls.Border)(target));
+ return;
+ case 8:
+ this.Num1 = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 9:
+ this.Label1 = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 10:
+ this.Line1 = ((System.Windows.Controls.Border)(target));
+ return;
+ case 11:
+ this.Dot2 = ((System.Windows.Controls.Border)(target));
+ return;
+ case 12:
+ this.Num2 = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 13:
+ this.Label2 = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 14:
+ this.Line2 = ((System.Windows.Controls.Border)(target));
+ return;
+ case 15:
+ this.ImportStepRow = ((System.Windows.Controls.StackPanel)(target));
+ return;
+ case 16:
+ this.Dot3 = ((System.Windows.Controls.Border)(target));
+ return;
+ case 17:
+ this.Num3 = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 18:
+ this.Label3 = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 19:
+ this.Line3 = ((System.Windows.Controls.Border)(target));
+ return;
+ case 20:
+ this.Dot4 = ((System.Windows.Controls.Border)(target));
+ return;
+ case 21:
+ this.Num4 = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 22:
+ this.Label4 = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 23:
+ this.WindowTitle = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 24:
+
+ #line 183 "..\..\..\MainWindow.xaml"
+ ((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.Minimize_Click);
+
+ #line default
+ #line hidden
+ return;
+ case 25:
+ this.CloseButton = ((System.Windows.Controls.Button)(target));
+
+ #line 185 "..\..\..\MainWindow.xaml"
+ this.CloseButton.Click += new System.Windows.RoutedEventHandler(this.Cancel_Click);
+
+ #line default
+ #line hidden
+ return;
+ case 26:
+ this.PageWelcome = ((System.Windows.Controls.StackPanel)(target));
+ return;
+ case 27:
+ this.UpdateHint = ((System.Windows.Controls.Border)(target));
+ return;
+ case 28:
+ this.UpdateHintText = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 29:
+ this.RunningHint = ((System.Windows.Controls.Border)(target));
+ return;
+ case 30:
+ this.PageLicense = ((System.Windows.Controls.DockPanel)(target));
+ return;
+ case 31:
+ this.AcceptLicense = ((System.Windows.Controls.CheckBox)(target));
+
+ #line 265 "..\..\..\MainWindow.xaml"
+ this.AcceptLicense.Checked += new System.Windows.RoutedEventHandler(this.AcceptLicense_Click);
+
+ #line default
+ #line hidden
+
+ #line 265 "..\..\..\MainWindow.xaml"
+ this.AcceptLicense.Unchecked += new System.Windows.RoutedEventHandler(this.AcceptLicense_Click);
+
+ #line default
+ #line hidden
+ return;
+ case 32:
+ this.LicenseText = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 33:
+ this.PageOptions = ((System.Windows.Controls.StackPanel)(target));
+ return;
+ case 34:
+
+ #line 285 "..\..\..\MainWindow.xaml"
+ ((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.ChangeDir_Click);
+
+ #line default
+ #line hidden
+ return;
+ case 35:
+ this.DirBox = ((System.Windows.Controls.TextBox)(target));
+ return;
+ case 36:
+ this.DesktopLinkBox = ((System.Windows.Controls.CheckBox)(target));
+ return;
+ case 37:
+ this.StartMenuBox = ((System.Windows.Controls.CheckBox)(target));
+ return;
+ case 38:
+ this.PageImport = ((System.Windows.Controls.StackPanel)(target));
+ return;
+ case 39:
+ this.ImportList = ((System.Windows.Controls.StackPanel)(target));
+ return;
+ case 40:
+ this.PageProgress = ((System.Windows.Controls.StackPanel)(target));
+ return;
+ case 41:
+ this.SuccessIcon = ((System.Windows.Controls.Border)(target));
+ return;
+ case 42:
+ this.SuccessScale = ((System.Windows.Media.ScaleTransform)(target));
+ return;
+ case 43:
+ this.ProgressTitle = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 44:
+ this.ProgressBarPanel = ((System.Windows.Controls.StackPanel)(target));
+ return;
+ case 45:
+ this.PercentText = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 46:
+ this.ProgressTrack = ((System.Windows.Controls.Border)(target));
+
+ #line 327 "..\..\..\MainWindow.xaml"
+ this.ProgressTrack.SizeChanged += new System.Windows.SizeChangedEventHandler(this.ProgressTrack_SizeChanged);
+
+ #line default
+ #line hidden
+ return;
+ case 47:
+ this.ProgressFill = ((System.Windows.Controls.Border)(target));
+ return;
+ case 48:
+ this.ProgressText = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 49:
+ this.DonePanel = ((System.Windows.Controls.StackPanel)(target));
+ return;
+ case 50:
+ this.LaunchBox = ((System.Windows.Controls.CheckBox)(target));
+ return;
+ case 51:
+ this.PageUninstall = ((System.Windows.Controls.StackPanel)(target));
+ return;
+ case 52:
+ this.DataInfo = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 53:
+ this.RemoveDataBox = ((System.Windows.Controls.CheckBox)(target));
+
+ #line 352 "..\..\..\MainWindow.xaml"
+ this.RemoveDataBox.Checked += new System.Windows.RoutedEventHandler(this.RemoveDataBox_Click);
+
+ #line default
+ #line hidden
+
+ #line 352 "..\..\..\MainWindow.xaml"
+ this.RemoveDataBox.Unchecked += new System.Windows.RoutedEventHandler(this.RemoveDataBox_Click);
+
+ #line default
+ #line hidden
+ return;
+ case 54:
+ this.RemoveDataWarning = ((System.Windows.Controls.TextBlock)(target));
+ return;
+ case 55:
+ this.BackButton = ((System.Windows.Controls.Button)(target));
+
+ #line 363 "..\..\..\MainWindow.xaml"
+ this.BackButton.Click += new System.Windows.RoutedEventHandler(this.Back_Click);
+
+ #line default
+ #line hidden
+ return;
+ case 56:
+ this.NextButton = ((System.Windows.Controls.Button)(target));
+
+ #line 364 "..\..\..\MainWindow.xaml"
+ this.NextButton.Click += new System.Windows.RoutedEventHandler(this.Next_Click);
+
+ #line default
+ #line hidden
+ return;
+ case 57:
+ this.CancelButton = ((System.Windows.Controls.Button)(target));
+
+ #line 365 "..\..\..\MainWindow.xaml"
+ this.CancelButton.Click += new System.Windows.RoutedEventHandler(this.Cancel_Click);
+
+ #line default
+ #line hidden
+ return;
+ }
+ this._contentLoaded = true;
+ }
+ }
+}
+
diff --git a/installer/obj/Release/net48/Themes/Colors.Dark.baml b/installer/obj/Release/net48/Themes/Colors.Dark.baml
new file mode 100644
index 0000000..17c32ce
Binary files /dev/null and b/installer/obj/Release/net48/Themes/Colors.Dark.baml differ
diff --git a/installer/obj/Release/net48/Themes/Colors.Light.baml b/installer/obj/Release/net48/Themes/Colors.Light.baml
new file mode 100644
index 0000000..8d10637
Binary files /dev/null and b/installer/obj/Release/net48/Themes/Colors.Light.baml differ
diff --git a/installer/obj/Release/net48/Themes/Controls.baml b/installer/obj/Release/net48/Themes/Controls.baml
new file mode 100644
index 0000000..e82be68
Binary files /dev/null and b/installer/obj/Release/net48/Themes/Controls.baml differ
diff --git a/installer/obj/project.assets.json b/installer/obj/project.assets.json
new file mode 100644
index 0000000..7d5d338
--- /dev/null
+++ b/installer/obj/project.assets.json
@@ -0,0 +1,471 @@
+{
+ "version": 3,
+ "targets": {
+ ".NETFramework,Version=v4.8": {
+ "Microsoft.NETFramework.ReferenceAssemblies/1.0.3": {
+ "type": "package",
+ "dependencies": {
+ "Microsoft.NETFramework.ReferenceAssemblies.net48": "1.0.3"
+ }
+ },
+ "Microsoft.NETFramework.ReferenceAssemblies.net48/1.0.3": {
+ "type": "package",
+ "build": {
+ "build/Microsoft.NETFramework.ReferenceAssemblies.net48.targets": {}
+ }
+ }
+ }
+ },
+ "libraries": {
+ "Microsoft.NETFramework.ReferenceAssemblies/1.0.3": {
+ "sha512": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
+ "type": "package",
+ "path": "microsoft.netframework.referenceassemblies/1.0.3",
+ "files": [
+ ".nupkg.metadata",
+ ".signature.p7s",
+ "microsoft.netframework.referenceassemblies.1.0.3.nupkg.sha512",
+ "microsoft.netframework.referenceassemblies.nuspec"
+ ]
+ },
+ "Microsoft.NETFramework.ReferenceAssemblies.net48/1.0.3": {
+ "sha512": "zMk4D+9zyiEWByyQ7oPImPN/Jhpj166Ky0Nlla4eXlNL8hI/BtSJsgR8Inldd4NNpIAH3oh8yym0W2DrhXdSLQ==",
+ "type": "package",
+ "path": "microsoft.netframework.referenceassemblies.net48/1.0.3",
+ "files": [
+ ".nupkg.metadata",
+ ".signature.p7s",
+ "build/.NETFramework/v4.8/Accessibility.dll",
+ "build/.NETFramework/v4.8/Accessibility.xml",
+ "build/.NETFramework/v4.8/CustomMarshalers.dll",
+ "build/.NETFramework/v4.8/CustomMarshalers.xml",
+ "build/.NETFramework/v4.8/Facades/Microsoft.Win32.Primitives.dll",
+ "build/.NETFramework/v4.8/Facades/System.AppContext.dll",
+ "build/.NETFramework/v4.8/Facades/System.Collections.Concurrent.dll",
+ "build/.NETFramework/v4.8/Facades/System.Collections.NonGeneric.dll",
+ "build/.NETFramework/v4.8/Facades/System.Collections.Specialized.dll",
+ "build/.NETFramework/v4.8/Facades/System.Collections.dll",
+ "build/.NETFramework/v4.8/Facades/System.ComponentModel.Annotations.dll",
+ "build/.NETFramework/v4.8/Facades/System.ComponentModel.EventBasedAsync.dll",
+ "build/.NETFramework/v4.8/Facades/System.ComponentModel.Primitives.dll",
+ "build/.NETFramework/v4.8/Facades/System.ComponentModel.TypeConverter.dll",
+ "build/.NETFramework/v4.8/Facades/System.ComponentModel.dll",
+ "build/.NETFramework/v4.8/Facades/System.Console.dll",
+ "build/.NETFramework/v4.8/Facades/System.Data.Common.dll",
+ "build/.NETFramework/v4.8/Facades/System.Diagnostics.Contracts.dll",
+ "build/.NETFramework/v4.8/Facades/System.Diagnostics.Debug.dll",
+ "build/.NETFramework/v4.8/Facades/System.Diagnostics.FileVersionInfo.dll",
+ "build/.NETFramework/v4.8/Facades/System.Diagnostics.Process.dll",
+ "build/.NETFramework/v4.8/Facades/System.Diagnostics.StackTrace.dll",
+ "build/.NETFramework/v4.8/Facades/System.Diagnostics.TextWriterTraceListener.dll",
+ "build/.NETFramework/v4.8/Facades/System.Diagnostics.Tools.dll",
+ "build/.NETFramework/v4.8/Facades/System.Diagnostics.TraceSource.dll",
+ "build/.NETFramework/v4.8/Facades/System.Drawing.Primitives.dll",
+ "build/.NETFramework/v4.8/Facades/System.Dynamic.Runtime.dll",
+ "build/.NETFramework/v4.8/Facades/System.Globalization.Calendars.dll",
+ "build/.NETFramework/v4.8/Facades/System.Globalization.Extensions.dll",
+ "build/.NETFramework/v4.8/Facades/System.Globalization.dll",
+ "build/.NETFramework/v4.8/Facades/System.IO.Compression.ZipFile.dll",
+ "build/.NETFramework/v4.8/Facades/System.IO.FileSystem.DriveInfo.dll",
+ "build/.NETFramework/v4.8/Facades/System.IO.FileSystem.Primitives.dll",
+ "build/.NETFramework/v4.8/Facades/System.IO.FileSystem.Watcher.dll",
+ "build/.NETFramework/v4.8/Facades/System.IO.FileSystem.dll",
+ "build/.NETFramework/v4.8/Facades/System.IO.IsolatedStorage.dll",
+ "build/.NETFramework/v4.8/Facades/System.IO.MemoryMappedFiles.dll",
+ "build/.NETFramework/v4.8/Facades/System.IO.Pipes.dll",
+ "build/.NETFramework/v4.8/Facades/System.IO.UnmanagedMemoryStream.dll",
+ "build/.NETFramework/v4.8/Facades/System.IO.dll",
+ "build/.NETFramework/v4.8/Facades/System.Linq.Expressions.dll",
+ "build/.NETFramework/v4.8/Facades/System.Linq.Parallel.dll",
+ "build/.NETFramework/v4.8/Facades/System.Linq.Queryable.dll",
+ "build/.NETFramework/v4.8/Facades/System.Linq.dll",
+ "build/.NETFramework/v4.8/Facades/System.Net.Http.Rtc.dll",
+ "build/.NETFramework/v4.8/Facades/System.Net.NameResolution.dll",
+ "build/.NETFramework/v4.8/Facades/System.Net.NetworkInformation.dll",
+ "build/.NETFramework/v4.8/Facades/System.Net.Ping.dll",
+ "build/.NETFramework/v4.8/Facades/System.Net.Primitives.dll",
+ "build/.NETFramework/v4.8/Facades/System.Net.Requests.dll",
+ "build/.NETFramework/v4.8/Facades/System.Net.Security.dll",
+ "build/.NETFramework/v4.8/Facades/System.Net.Sockets.dll",
+ "build/.NETFramework/v4.8/Facades/System.Net.WebHeaderCollection.dll",
+ "build/.NETFramework/v4.8/Facades/System.Net.WebSockets.Client.dll",
+ "build/.NETFramework/v4.8/Facades/System.Net.WebSockets.dll",
+ "build/.NETFramework/v4.8/Facades/System.ObjectModel.dll",
+ "build/.NETFramework/v4.8/Facades/System.Reflection.Emit.ILGeneration.dll",
+ "build/.NETFramework/v4.8/Facades/System.Reflection.Emit.Lightweight.dll",
+ "build/.NETFramework/v4.8/Facades/System.Reflection.Emit.dll",
+ "build/.NETFramework/v4.8/Facades/System.Reflection.Extensions.dll",
+ "build/.NETFramework/v4.8/Facades/System.Reflection.Primitives.dll",
+ "build/.NETFramework/v4.8/Facades/System.Reflection.dll",
+ "build/.NETFramework/v4.8/Facades/System.Resources.Reader.dll",
+ "build/.NETFramework/v4.8/Facades/System.Resources.ResourceManager.dll",
+ "build/.NETFramework/v4.8/Facades/System.Resources.Writer.dll",
+ "build/.NETFramework/v4.8/Facades/System.Runtime.CompilerServices.VisualC.dll",
+ "build/.NETFramework/v4.8/Facades/System.Runtime.Extensions.dll",
+ "build/.NETFramework/v4.8/Facades/System.Runtime.Handles.dll",
+ "build/.NETFramework/v4.8/Facades/System.Runtime.InteropServices.RuntimeInformation.dll",
+ "build/.NETFramework/v4.8/Facades/System.Runtime.InteropServices.WindowsRuntime.dll",
+ "build/.NETFramework/v4.8/Facades/System.Runtime.InteropServices.dll",
+ "build/.NETFramework/v4.8/Facades/System.Runtime.Numerics.dll",
+ "build/.NETFramework/v4.8/Facades/System.Runtime.Serialization.Formatters.dll",
+ "build/.NETFramework/v4.8/Facades/System.Runtime.Serialization.Json.dll",
+ "build/.NETFramework/v4.8/Facades/System.Runtime.Serialization.Primitives.dll",
+ "build/.NETFramework/v4.8/Facades/System.Runtime.Serialization.Xml.dll",
+ "build/.NETFramework/v4.8/Facades/System.Runtime.dll",
+ "build/.NETFramework/v4.8/Facades/System.Security.Claims.dll",
+ "build/.NETFramework/v4.8/Facades/System.Security.Cryptography.Algorithms.dll",
+ "build/.NETFramework/v4.8/Facades/System.Security.Cryptography.Csp.dll",
+ "build/.NETFramework/v4.8/Facades/System.Security.Cryptography.Encoding.dll",
+ "build/.NETFramework/v4.8/Facades/System.Security.Cryptography.Primitives.dll",
+ "build/.NETFramework/v4.8/Facades/System.Security.Cryptography.X509Certificates.dll",
+ "build/.NETFramework/v4.8/Facades/System.Security.Principal.dll",
+ "build/.NETFramework/v4.8/Facades/System.Security.SecureString.dll",
+ "build/.NETFramework/v4.8/Facades/System.ServiceModel.Duplex.dll",
+ "build/.NETFramework/v4.8/Facades/System.ServiceModel.Http.dll",
+ "build/.NETFramework/v4.8/Facades/System.ServiceModel.NetTcp.dll",
+ "build/.NETFramework/v4.8/Facades/System.ServiceModel.Primitives.dll",
+ "build/.NETFramework/v4.8/Facades/System.ServiceModel.Security.dll",
+ "build/.NETFramework/v4.8/Facades/System.Text.Encoding.Extensions.dll",
+ "build/.NETFramework/v4.8/Facades/System.Text.Encoding.dll",
+ "build/.NETFramework/v4.8/Facades/System.Text.RegularExpressions.dll",
+ "build/.NETFramework/v4.8/Facades/System.Threading.Overlapped.dll",
+ "build/.NETFramework/v4.8/Facades/System.Threading.Tasks.Parallel.dll",
+ "build/.NETFramework/v4.8/Facades/System.Threading.Tasks.dll",
+ "build/.NETFramework/v4.8/Facades/System.Threading.Thread.dll",
+ "build/.NETFramework/v4.8/Facades/System.Threading.ThreadPool.dll",
+ "build/.NETFramework/v4.8/Facades/System.Threading.Timer.dll",
+ "build/.NETFramework/v4.8/Facades/System.Threading.dll",
+ "build/.NETFramework/v4.8/Facades/System.ValueTuple.dll",
+ "build/.NETFramework/v4.8/Facades/System.Xml.ReaderWriter.dll",
+ "build/.NETFramework/v4.8/Facades/System.Xml.XDocument.dll",
+ "build/.NETFramework/v4.8/Facades/System.Xml.XPath.XDocument.dll",
+ "build/.NETFramework/v4.8/Facades/System.Xml.XPath.dll",
+ "build/.NETFramework/v4.8/Facades/System.Xml.XmlDocument.dll",
+ "build/.NETFramework/v4.8/Facades/System.Xml.XmlSerializer.dll",
+ "build/.NETFramework/v4.8/Facades/netstandard.dll",
+ "build/.NETFramework/v4.8/ISymWrapper.dll",
+ "build/.NETFramework/v4.8/ISymWrapper.xml",
+ "build/.NETFramework/v4.8/Microsoft.Activities.Build.dll",
+ "build/.NETFramework/v4.8/Microsoft.Activities.Build.xml",
+ "build/.NETFramework/v4.8/Microsoft.Build.Conversion.v4.0.dll",
+ "build/.NETFramework/v4.8/Microsoft.Build.Conversion.v4.0.xml",
+ "build/.NETFramework/v4.8/Microsoft.Build.Engine.dll",
+ "build/.NETFramework/v4.8/Microsoft.Build.Engine.xml",
+ "build/.NETFramework/v4.8/Microsoft.Build.Framework.dll",
+ "build/.NETFramework/v4.8/Microsoft.Build.Framework.xml",
+ "build/.NETFramework/v4.8/Microsoft.Build.Tasks.v4.0.dll",
+ "build/.NETFramework/v4.8/Microsoft.Build.Tasks.v4.0.xml",
+ "build/.NETFramework/v4.8/Microsoft.Build.Utilities.v4.0.dll",
+ "build/.NETFramework/v4.8/Microsoft.Build.Utilities.v4.0.xml",
+ "build/.NETFramework/v4.8/Microsoft.Build.dll",
+ "build/.NETFramework/v4.8/Microsoft.Build.xml",
+ "build/.NETFramework/v4.8/Microsoft.CSharp.dll",
+ "build/.NETFramework/v4.8/Microsoft.CSharp.xml",
+ "build/.NETFramework/v4.8/Microsoft.JScript.dll",
+ "build/.NETFramework/v4.8/Microsoft.JScript.xml",
+ "build/.NETFramework/v4.8/Microsoft.VisualBasic.Compatibility.Data.dll",
+ "build/.NETFramework/v4.8/Microsoft.VisualBasic.Compatibility.Data.xml",
+ "build/.NETFramework/v4.8/Microsoft.VisualBasic.Compatibility.dll",
+ "build/.NETFramework/v4.8/Microsoft.VisualBasic.Compatibility.xml",
+ "build/.NETFramework/v4.8/Microsoft.VisualBasic.dll",
+ "build/.NETFramework/v4.8/Microsoft.VisualBasic.xml",
+ "build/.NETFramework/v4.8/Microsoft.VisualC.STLCLR.dll",
+ "build/.NETFramework/v4.8/Microsoft.VisualC.STLCLR.xml",
+ "build/.NETFramework/v4.8/Microsoft.VisualC.dll",
+ "build/.NETFramework/v4.8/Microsoft.VisualC.xml",
+ "build/.NETFramework/v4.8/PermissionSets/FullTrust.xml",
+ "build/.NETFramework/v4.8/PermissionSets/Internet.xml",
+ "build/.NETFramework/v4.8/PermissionSets/LocalIntranet.xml",
+ "build/.NETFramework/v4.8/PresentationBuildTasks.dll",
+ "build/.NETFramework/v4.8/PresentationBuildTasks.xml",
+ "build/.NETFramework/v4.8/PresentationCore.dll",
+ "build/.NETFramework/v4.8/PresentationCore.xml",
+ "build/.NETFramework/v4.8/PresentationFramework.Aero.dll",
+ "build/.NETFramework/v4.8/PresentationFramework.Aero.xml",
+ "build/.NETFramework/v4.8/PresentationFramework.Aero2.dll",
+ "build/.NETFramework/v4.8/PresentationFramework.Aero2.xml",
+ "build/.NETFramework/v4.8/PresentationFramework.AeroLite.dll",
+ "build/.NETFramework/v4.8/PresentationFramework.AeroLite.xml",
+ "build/.NETFramework/v4.8/PresentationFramework.Classic.dll",
+ "build/.NETFramework/v4.8/PresentationFramework.Classic.xml",
+ "build/.NETFramework/v4.8/PresentationFramework.Luna.dll",
+ "build/.NETFramework/v4.8/PresentationFramework.Luna.xml",
+ "build/.NETFramework/v4.8/PresentationFramework.Royale.dll",
+ "build/.NETFramework/v4.8/PresentationFramework.Royale.xml",
+ "build/.NETFramework/v4.8/PresentationFramework.dll",
+ "build/.NETFramework/v4.8/PresentationFramework.xml",
+ "build/.NETFramework/v4.8/ReachFramework.dll",
+ "build/.NETFramework/v4.8/ReachFramework.xml",
+ "build/.NETFramework/v4.8/RedistList/FrameworkList.xml",
+ "build/.NETFramework/v4.8/System.Activities.Core.Presentation.dll",
+ "build/.NETFramework/v4.8/System.Activities.Core.Presentation.xml",
+ "build/.NETFramework/v4.8/System.Activities.DurableInstancing.dll",
+ "build/.NETFramework/v4.8/System.Activities.DurableInstancing.xml",
+ "build/.NETFramework/v4.8/System.Activities.Presentation.dll",
+ "build/.NETFramework/v4.8/System.Activities.Presentation.xml",
+ "build/.NETFramework/v4.8/System.Activities.dll",
+ "build/.NETFramework/v4.8/System.Activities.xml",
+ "build/.NETFramework/v4.8/System.AddIn.Contract.dll",
+ "build/.NETFramework/v4.8/System.AddIn.Contract.xml",
+ "build/.NETFramework/v4.8/System.AddIn.dll",
+ "build/.NETFramework/v4.8/System.AddIn.xml",
+ "build/.NETFramework/v4.8/System.ComponentModel.Composition.Registration.dll",
+ "build/.NETFramework/v4.8/System.ComponentModel.Composition.Registration.xml",
+ "build/.NETFramework/v4.8/System.ComponentModel.Composition.dll",
+ "build/.NETFramework/v4.8/System.ComponentModel.Composition.xml",
+ "build/.NETFramework/v4.8/System.ComponentModel.DataAnnotations.dll",
+ "build/.NETFramework/v4.8/System.ComponentModel.DataAnnotations.xml",
+ "build/.NETFramework/v4.8/System.Configuration.Install.dll",
+ "build/.NETFramework/v4.8/System.Configuration.Install.xml",
+ "build/.NETFramework/v4.8/System.Configuration.dll",
+ "build/.NETFramework/v4.8/System.Configuration.xml",
+ "build/.NETFramework/v4.8/System.Core.dll",
+ "build/.NETFramework/v4.8/System.Core.xml",
+ "build/.NETFramework/v4.8/System.Data.DataSetExtensions.dll",
+ "build/.NETFramework/v4.8/System.Data.DataSetExtensions.xml",
+ "build/.NETFramework/v4.8/System.Data.Entity.Design.dll",
+ "build/.NETFramework/v4.8/System.Data.Entity.Design.xml",
+ "build/.NETFramework/v4.8/System.Data.Entity.dll",
+ "build/.NETFramework/v4.8/System.Data.Entity.xml",
+ "build/.NETFramework/v4.8/System.Data.Linq.dll",
+ "build/.NETFramework/v4.8/System.Data.Linq.xml",
+ "build/.NETFramework/v4.8/System.Data.OracleClient.dll",
+ "build/.NETFramework/v4.8/System.Data.OracleClient.xml",
+ "build/.NETFramework/v4.8/System.Data.Services.Client.dll",
+ "build/.NETFramework/v4.8/System.Data.Services.Client.xml",
+ "build/.NETFramework/v4.8/System.Data.Services.Design.dll",
+ "build/.NETFramework/v4.8/System.Data.Services.Design.xml",
+ "build/.NETFramework/v4.8/System.Data.Services.dll",
+ "build/.NETFramework/v4.8/System.Data.Services.xml",
+ "build/.NETFramework/v4.8/System.Data.SqlXml.dll",
+ "build/.NETFramework/v4.8/System.Data.SqlXml.xml",
+ "build/.NETFramework/v4.8/System.Data.dll",
+ "build/.NETFramework/v4.8/System.Data.xml",
+ "build/.NETFramework/v4.8/System.Deployment.dll",
+ "build/.NETFramework/v4.8/System.Deployment.xml",
+ "build/.NETFramework/v4.8/System.Design.dll",
+ "build/.NETFramework/v4.8/System.Design.xml",
+ "build/.NETFramework/v4.8/System.Device.dll",
+ "build/.NETFramework/v4.8/System.Device.xml",
+ "build/.NETFramework/v4.8/System.Diagnostics.Tracing.dll",
+ "build/.NETFramework/v4.8/System.Diagnostics.Tracing.xml",
+ "build/.NETFramework/v4.8/System.DirectoryServices.AccountManagement.dll",
+ "build/.NETFramework/v4.8/System.DirectoryServices.AccountManagement.xml",
+ "build/.NETFramework/v4.8/System.DirectoryServices.Protocols.dll",
+ "build/.NETFramework/v4.8/System.DirectoryServices.Protocols.xml",
+ "build/.NETFramework/v4.8/System.DirectoryServices.dll",
+ "build/.NETFramework/v4.8/System.DirectoryServices.xml",
+ "build/.NETFramework/v4.8/System.Drawing.Design.dll",
+ "build/.NETFramework/v4.8/System.Drawing.Design.xml",
+ "build/.NETFramework/v4.8/System.Drawing.dll",
+ "build/.NETFramework/v4.8/System.Drawing.xml",
+ "build/.NETFramework/v4.8/System.Dynamic.dll",
+ "build/.NETFramework/v4.8/System.EnterpriseServices.Thunk.dll",
+ "build/.NETFramework/v4.8/System.EnterpriseServices.Wrapper.dll",
+ "build/.NETFramework/v4.8/System.EnterpriseServices.dll",
+ "build/.NETFramework/v4.8/System.EnterpriseServices.xml",
+ "build/.NETFramework/v4.8/System.IO.Compression.FileSystem.dll",
+ "build/.NETFramework/v4.8/System.IO.Compression.FileSystem.xml",
+ "build/.NETFramework/v4.8/System.IO.Compression.dll",
+ "build/.NETFramework/v4.8/System.IO.Compression.xml",
+ "build/.NETFramework/v4.8/System.IO.Log.dll",
+ "build/.NETFramework/v4.8/System.IO.Log.xml",
+ "build/.NETFramework/v4.8/System.IdentityModel.Selectors.dll",
+ "build/.NETFramework/v4.8/System.IdentityModel.Selectors.xml",
+ "build/.NETFramework/v4.8/System.IdentityModel.Services.dll",
+ "build/.NETFramework/v4.8/System.IdentityModel.Services.xml",
+ "build/.NETFramework/v4.8/System.IdentityModel.dll",
+ "build/.NETFramework/v4.8/System.IdentityModel.xml",
+ "build/.NETFramework/v4.8/System.Linq.xml",
+ "build/.NETFramework/v4.8/System.Management.Instrumentation.dll",
+ "build/.NETFramework/v4.8/System.Management.Instrumentation.xml",
+ "build/.NETFramework/v4.8/System.Management.dll",
+ "build/.NETFramework/v4.8/System.Management.xml",
+ "build/.NETFramework/v4.8/System.Messaging.dll",
+ "build/.NETFramework/v4.8/System.Messaging.xml",
+ "build/.NETFramework/v4.8/System.Net.Http.WebRequest.dll",
+ "build/.NETFramework/v4.8/System.Net.Http.WebRequest.xml",
+ "build/.NETFramework/v4.8/System.Net.Http.dll",
+ "build/.NETFramework/v4.8/System.Net.Http.xml",
+ "build/.NETFramework/v4.8/System.Net.dll",
+ "build/.NETFramework/v4.8/System.Net.xml",
+ "build/.NETFramework/v4.8/System.Numerics.dll",
+ "build/.NETFramework/v4.8/System.Numerics.xml",
+ "build/.NETFramework/v4.8/System.Printing.dll",
+ "build/.NETFramework/v4.8/System.Printing.xml",
+ "build/.NETFramework/v4.8/System.Reflection.Context.dll",
+ "build/.NETFramework/v4.8/System.Reflection.Context.xml",
+ "build/.NETFramework/v4.8/System.Runtime.Caching.dll",
+ "build/.NETFramework/v4.8/System.Runtime.Caching.xml",
+ "build/.NETFramework/v4.8/System.Runtime.DurableInstancing.dll",
+ "build/.NETFramework/v4.8/System.Runtime.DurableInstancing.xml",
+ "build/.NETFramework/v4.8/System.Runtime.Remoting.dll",
+ "build/.NETFramework/v4.8/System.Runtime.Remoting.xml",
+ "build/.NETFramework/v4.8/System.Runtime.Serialization.Formatters.Soap.dll",
+ "build/.NETFramework/v4.8/System.Runtime.Serialization.Formatters.Soap.xml",
+ "build/.NETFramework/v4.8/System.Runtime.Serialization.dll",
+ "build/.NETFramework/v4.8/System.Runtime.Serialization.xml",
+ "build/.NETFramework/v4.8/System.Security.dll",
+ "build/.NETFramework/v4.8/System.Security.xml",
+ "build/.NETFramework/v4.8/System.ServiceModel.Activation.dll",
+ "build/.NETFramework/v4.8/System.ServiceModel.Activation.xml",
+ "build/.NETFramework/v4.8/System.ServiceModel.Activities.dll",
+ "build/.NETFramework/v4.8/System.ServiceModel.Activities.xml",
+ "build/.NETFramework/v4.8/System.ServiceModel.Channels.dll",
+ "build/.NETFramework/v4.8/System.ServiceModel.Channels.xml",
+ "build/.NETFramework/v4.8/System.ServiceModel.Discovery.dll",
+ "build/.NETFramework/v4.8/System.ServiceModel.Discovery.xml",
+ "build/.NETFramework/v4.8/System.ServiceModel.Routing.dll",
+ "build/.NETFramework/v4.8/System.ServiceModel.Routing.xml",
+ "build/.NETFramework/v4.8/System.ServiceModel.Web.dll",
+ "build/.NETFramework/v4.8/System.ServiceModel.Web.xml",
+ "build/.NETFramework/v4.8/System.ServiceModel.dll",
+ "build/.NETFramework/v4.8/System.ServiceModel.xml",
+ "build/.NETFramework/v4.8/System.ServiceProcess.dll",
+ "build/.NETFramework/v4.8/System.ServiceProcess.xml",
+ "build/.NETFramework/v4.8/System.Speech.dll",
+ "build/.NETFramework/v4.8/System.Speech.xml",
+ "build/.NETFramework/v4.8/System.Threading.Tasks.Dataflow.xml",
+ "build/.NETFramework/v4.8/System.Transactions.dll",
+ "build/.NETFramework/v4.8/System.Transactions.xml",
+ "build/.NETFramework/v4.8/System.Web.Abstractions.dll",
+ "build/.NETFramework/v4.8/System.Web.ApplicationServices.dll",
+ "build/.NETFramework/v4.8/System.Web.ApplicationServices.xml",
+ "build/.NETFramework/v4.8/System.Web.DataVisualization.Design.dll",
+ "build/.NETFramework/v4.8/System.Web.DataVisualization.dll",
+ "build/.NETFramework/v4.8/System.Web.DataVisualization.xml",
+ "build/.NETFramework/v4.8/System.Web.DynamicData.Design.dll",
+ "build/.NETFramework/v4.8/System.Web.DynamicData.Design.xml",
+ "build/.NETFramework/v4.8/System.Web.DynamicData.dll",
+ "build/.NETFramework/v4.8/System.Web.DynamicData.xml",
+ "build/.NETFramework/v4.8/System.Web.Entity.Design.dll",
+ "build/.NETFramework/v4.8/System.Web.Entity.Design.xml",
+ "build/.NETFramework/v4.8/System.Web.Entity.dll",
+ "build/.NETFramework/v4.8/System.Web.Entity.xml",
+ "build/.NETFramework/v4.8/System.Web.Extensions.Design.dll",
+ "build/.NETFramework/v4.8/System.Web.Extensions.Design.xml",
+ "build/.NETFramework/v4.8/System.Web.Extensions.dll",
+ "build/.NETFramework/v4.8/System.Web.Extensions.xml",
+ "build/.NETFramework/v4.8/System.Web.Mobile.dll",
+ "build/.NETFramework/v4.8/System.Web.Mobile.xml",
+ "build/.NETFramework/v4.8/System.Web.RegularExpressions.dll",
+ "build/.NETFramework/v4.8/System.Web.RegularExpressions.xml",
+ "build/.NETFramework/v4.8/System.Web.Routing.dll",
+ "build/.NETFramework/v4.8/System.Web.Services.dll",
+ "build/.NETFramework/v4.8/System.Web.Services.xml",
+ "build/.NETFramework/v4.8/System.Web.dll",
+ "build/.NETFramework/v4.8/System.Web.xml",
+ "build/.NETFramework/v4.8/System.Windows.Controls.Ribbon.dll",
+ "build/.NETFramework/v4.8/System.Windows.Controls.Ribbon.xml",
+ "build/.NETFramework/v4.8/System.Windows.Forms.DataVisualization.Design.dll",
+ "build/.NETFramework/v4.8/System.Windows.Forms.DataVisualization.dll",
+ "build/.NETFramework/v4.8/System.Windows.Forms.DataVisualization.xml",
+ "build/.NETFramework/v4.8/System.Windows.Forms.dll",
+ "build/.NETFramework/v4.8/System.Windows.Forms.xml",
+ "build/.NETFramework/v4.8/System.Windows.Input.Manipulations.dll",
+ "build/.NETFramework/v4.8/System.Windows.Input.Manipulations.xml",
+ "build/.NETFramework/v4.8/System.Windows.Presentation.dll",
+ "build/.NETFramework/v4.8/System.Windows.Presentation.xml",
+ "build/.NETFramework/v4.8/System.Windows.dll",
+ "build/.NETFramework/v4.8/System.Workflow.Activities.dll",
+ "build/.NETFramework/v4.8/System.Workflow.Activities.xml",
+ "build/.NETFramework/v4.8/System.Workflow.ComponentModel.dll",
+ "build/.NETFramework/v4.8/System.Workflow.ComponentModel.xml",
+ "build/.NETFramework/v4.8/System.Workflow.Runtime.dll",
+ "build/.NETFramework/v4.8/System.Workflow.Runtime.xml",
+ "build/.NETFramework/v4.8/System.WorkflowServices.dll",
+ "build/.NETFramework/v4.8/System.WorkflowServices.xml",
+ "build/.NETFramework/v4.8/System.Xaml.dll",
+ "build/.NETFramework/v4.8/System.Xaml.xml",
+ "build/.NETFramework/v4.8/System.Xml.Linq.dll",
+ "build/.NETFramework/v4.8/System.Xml.Linq.xml",
+ "build/.NETFramework/v4.8/System.Xml.Serialization.dll",
+ "build/.NETFramework/v4.8/System.Xml.dll",
+ "build/.NETFramework/v4.8/System.Xml.xml",
+ "build/.NETFramework/v4.8/System.dll",
+ "build/.NETFramework/v4.8/System.xml",
+ "build/.NETFramework/v4.8/UIAutomationClient.dll",
+ "build/.NETFramework/v4.8/UIAutomationClient.xml",
+ "build/.NETFramework/v4.8/UIAutomationClientsideProviders.dll",
+ "build/.NETFramework/v4.8/UIAutomationClientsideProviders.xml",
+ "build/.NETFramework/v4.8/UIAutomationProvider.dll",
+ "build/.NETFramework/v4.8/UIAutomationProvider.xml",
+ "build/.NETFramework/v4.8/UIAutomationTypes.dll",
+ "build/.NETFramework/v4.8/UIAutomationTypes.xml",
+ "build/.NETFramework/v4.8/WindowsBase.dll",
+ "build/.NETFramework/v4.8/WindowsBase.xml",
+ "build/.NETFramework/v4.8/WindowsFormsIntegration.dll",
+ "build/.NETFramework/v4.8/WindowsFormsIntegration.xml",
+ "build/.NETFramework/v4.8/XamlBuildTask.dll",
+ "build/.NETFramework/v4.8/XamlBuildTask.xml",
+ "build/.NETFramework/v4.8/mscorlib.dll",
+ "build/.NETFramework/v4.8/mscorlib.xml",
+ "build/.NETFramework/v4.8/namespaces.xml",
+ "build/.NETFramework/v4.8/sysglobl.dll",
+ "build/.NETFramework/v4.8/sysglobl.xml",
+ "build/Microsoft.NETFramework.ReferenceAssemblies.net48.targets",
+ "microsoft.netframework.referenceassemblies.net48.1.0.3.nupkg.sha512",
+ "microsoft.netframework.referenceassemblies.net48.nuspec"
+ ]
+ }
+ },
+ "projectFileDependencyGroups": {
+ ".NETFramework,Version=v4.8": [
+ "Microsoft.NETFramework.ReferenceAssemblies >= 1.0.3"
+ ]
+ },
+ "packageFolders": {
+ "C:\\Users\\Viper\\.nuget\\packages\\": {}
+ },
+ "project": {
+ "version": "1.1.4",
+ "restore": {
+ "projectUniqueName": "C:\\Users\\Viper\\Desktop\\AeroMC-Launcher\\installer\\AeroMCSetup.csproj",
+ "projectName": "AeroMC-Setup",
+ "projectPath": "C:\\Users\\Viper\\Desktop\\AeroMC-Launcher\\installer\\AeroMCSetup.csproj",
+ "packagesPath": "C:\\Users\\Viper\\.nuget\\packages\\",
+ "outputPath": "C:\\Users\\Viper\\Desktop\\AeroMC-Launcher\\installer\\obj\\",
+ "projectStyle": "PackageReference",
+ "configFilePaths": [
+ "C:\\Users\\Viper\\AppData\\Roaming\\NuGet\\NuGet.Config"
+ ],
+ "originalTargetFrameworks": [
+ "net48"
+ ],
+ "sources": {
+ "https://api.nuget.org/v3/index.json": {}
+ },
+ "frameworks": {
+ "net48": {
+ "targetAlias": "net48",
+ "projectReferences": {}
+ }
+ },
+ "warningProperties": {
+ "warnAsError": [
+ "NU1605"
+ ]
+ },
+ "restoreAuditProperties": {
+ "enableAudit": "true",
+ "auditLevel": "low",
+ "auditMode": "direct"
+ },
+ "SdkAnalysisLevel": "10.0.100"
+ },
+ "frameworks": {
+ "net48": {
+ "targetAlias": "net48",
+ "dependencies": {
+ "Microsoft.NETFramework.ReferenceAssemblies": {
+ "suppressParent": "All",
+ "target": "Package",
+ "version": "[1.0.3, )",
+ "autoReferenced": true
+ }
+ },
+ "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.112\\RuntimeIdentifierGraph.json"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/installer/obj/project.nuget.cache b/installer/obj/project.nuget.cache
new file mode 100644
index 0000000..50c9bb1
--- /dev/null
+++ b/installer/obj/project.nuget.cache
@@ -0,0 +1,11 @@
+{
+ "version": 2,
+ "dgSpecHash": "LtLdHVMRd2c=",
+ "success": true,
+ "projectFilePath": "C:\\Users\\Viper\\Desktop\\AeroMC-Launcher\\installer\\AeroMCSetup.csproj",
+ "expectedPackageFiles": [
+ "C:\\Users\\Viper\\.nuget\\packages\\microsoft.netframework.referenceassemblies\\1.0.3\\microsoft.netframework.referenceassemblies.1.0.3.nupkg.sha512",
+ "C:\\Users\\Viper\\.nuget\\packages\\microsoft.netframework.referenceassemblies.net48\\1.0.3\\microsoft.netframework.referenceassemblies.net48.1.0.3.nupkg.sha512"
+ ],
+ "logs": []
+}
\ No newline at end of file
diff --git a/scripts/build-setup.js b/scripts/build-setup.js
new file mode 100644
index 0000000..225077c
--- /dev/null
+++ b/scripts/build-setup.js
@@ -0,0 +1,94 @@
+'use strict';
+
+/*
+ * build-setup.js – eigenes Setup (installer/) mit der App zusammenbauen
+ * ---------------------------------------------------------------------
+ * Läuft nach "electron-builder --win dir" (siehe "build" in package.json):
+ *
+ * 1. dist/win-unpacked (die fertige App) als ZIP packen
+ * 2. installer/ (WPF, .NET Framework 4.8) mit der Version aus package.json bauen
+ * 3. ZIP hinten an die Setup-.exe hängen:
+ * [Setup.exe][ZIP][8 Byte ZIP-Länge][8 Byte "AEROMCPK"]
+ * (das Setup liest den Anhang selbst aus, siehe installer/Payload.cs)
+ * 4. Zwischenstände wegräumen → übrig bleibt dist/AeroMC-Setup.exe
+ *
+ * Benötigt das .NET SDK (dotnet) – das Setup selbst läuft danach auf jedem
+ * Windows 10/11 ohne Zusatzinstallation.
+ */
+
+const fs = require('fs');
+const path = require('path');
+const { execFileSync } = require('child_process');
+
+const ROOT = path.join(__dirname, '..');
+const DIST = path.join(ROOT, 'dist');
+const APP_DIR = path.join(DIST, 'win-unpacked');
+const WORK = path.join(DIST, '.setup');
+const ZIP = path.join(WORK, 'app.zip');
+const OUT = path.join(DIST, 'AeroMC-Setup.exe');
+const MAGIC = Buffer.from('AEROMCPK', 'ascii');
+
+function schritt(text) {
+ console.log(`\n» ${text}`);
+}
+
+function main() {
+ const version = require(path.join(ROOT, 'package.json')).version;
+ if (!fs.existsSync(path.join(APP_DIR, 'AeroMC.exe'))) {
+ throw new Error(`${APP_DIR}\\AeroMC.exe fehlt – vorher "electron-builder --win dir" ausführen.`);
+ }
+ fs.rmSync(WORK, { recursive: true, force: true });
+ fs.mkdirSync(WORK, { recursive: true });
+
+ schritt('App wird gepackt …');
+ // .NET-ZIP über PowerShell: in jedem Windows enthalten, keine zusätzliche npm-Abhängigkeit
+ const ps = [
+ 'Add-Type -AssemblyName System.IO.Compression.FileSystem',
+ `[System.IO.Compression.ZipFile]::CreateFromDirectory('${APP_DIR.replace(/'/g, "''")}', '${ZIP.replace(/'/g, "''")}', [System.IO.Compression.CompressionLevel]::Optimal, $false)`,
+ ].join('; ');
+ execFileSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', ps], { stdio: 'inherit' });
+
+ schritt(`Setup ${version} wird gebaut …`);
+ const stubDir = path.join(WORK, 'stub');
+ execFileSync('dotnet', [
+ 'build', path.join(ROOT, 'installer', 'AeroMCSetup.csproj'),
+ '-c', 'Release', `-p:Version=${version}`, '-p:DebugType=none',
+ '--nologo', '-v', 'q', '-o', stubDir,
+ ], { stdio: 'inherit' });
+ const stub = path.join(stubDir, 'AeroMC-Setup.exe');
+ if (!fs.existsSync(stub)) throw new Error('Build des Setups fehlgeschlagen.');
+
+ schritt('App wird ans Setup angehängt …');
+ const zipSize = fs.statSync(ZIP).size;
+ const footer = Buffer.alloc(16);
+ footer.writeBigInt64LE(BigInt(zipSize), 0);
+ MAGIC.copy(footer, 8);
+ fs.rmSync(OUT, { force: true });
+ fs.copyFileSync(stub, OUT);
+ // ZIP in Blöcken anhängen statt komplett in den Speicher zu laden
+ const fd = fs.openSync(OUT, 'a');
+ try {
+ const src = fs.openSync(ZIP, 'r');
+ try {
+ const buf = Buffer.alloc(8 * 1024 * 1024);
+ let n;
+ while ((n = fs.readSync(src, buf, 0, buf.length, null)) > 0) fs.writeSync(fd, buf, 0, n);
+ } finally { fs.closeSync(src); }
+ fs.writeSync(fd, footer);
+ } finally { fs.closeSync(fd); }
+
+ schritt('Aufräumen …');
+ for (const t of [WORK, APP_DIR, path.join(DIST, 'builder-debug.yml'), path.join(DIST, 'builder-effective-config.yaml')]) {
+ fs.rmSync(t, { recursive: true, force: true });
+ }
+
+ const mb = (fs.statSync(OUT).size / 1024 / 1024).toFixed(1);
+ console.log(`\nFertig: ${OUT} (${mb} MB)`);
+}
+
+try {
+ main();
+} catch (err) {
+ console.error(`\nFehler: ${err.message}`);
+ process.exit(1);
+}