From 8d12206aa238b2507d47225981b5f77fef510e36 Mon Sep 17 00:00:00 2001 From: Sebastien Lebreton Date: Tue, 17 Sep 2024 08:39:05 +0200 Subject: [PATCH] Detect SPT-AKI install locations from MUI cache --- Installer/Installation.cs | 19 ++++------- Installer/Registry.cs | 68 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 Installer/Registry.cs diff --git a/Installer/Installation.cs b/Installer/Installation.cs index 56c53e0..5753c16 100644 --- a/Installer/Installation.cs +++ b/Installer/Installation.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Runtime.Versioning; using System.Text; -using Microsoft.Win32; using Spectre.Console; namespace Installer; @@ -95,18 +94,14 @@ private static IEnumerable DiscoverInstallations() if (TryDiscoverInstallation(Path.Combine(Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System))!, "SPT"), out installation)) yield return installation; - using var hive = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32); - using var eft = hive.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\EscapeFromTarkov", false); - - if (eft == null) - yield break; - - var exe = eft.GetValue("DisplayIcon") as string; - if (string.IsNullOrEmpty(exe) || !File.Exists(exe)) - yield break; + // SPT-AKI locations from MUI cache + foreach (var sptpath in Registry.GetSptAkiInstallationsFromMuiCache()) + { + if (TryDiscoverInstallation(sptpath, out installation)) + yield return installation; + } - var path = Path.GetDirectoryName(exe); - if (string.IsNullOrEmpty(path) || !Directory.Exists(path)) + if (!Registry.TryGetEscapeFromTarkovInstallationPath(out var path)) yield break; if (TryDiscoverInstallation(path, out installation)) diff --git a/Installer/Registry.cs b/Installer/Registry.cs new file mode 100644 index 0000000..802b52a --- /dev/null +++ b/Installer/Registry.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Runtime.Versioning; +using Microsoft.Win32; + +namespace Installer +{ + [SupportedOSPlatform("windows")] + internal class Registry + { + public static bool TryGetEscapeFromTarkovInstallationPath([NotNullWhen(true)] out string? installationPath) + { + installationPath = null; + + try + { + using var hive = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32); + using var eft = hive.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\EscapeFromTarkov", false); + + if (eft == null) + return false; + + var exe = eft.GetValue("DisplayIcon") as string; + if (string.IsNullOrEmpty(exe) || !File.Exists(exe)) + return false; + + var path = Path.GetDirectoryName(exe); + if (string.IsNullOrEmpty(path) || !Directory.Exists(path)) + return false; + + installationPath = path; + return true; + } + catch + { + return false; + } + } + + public static IEnumerable GetSptAkiInstallationsFromMuiCache() + { + try + { + using var hive = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry32); + using var mui = hive.OpenSubKey(@"Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache", false); + + if (mui == null) + return []; + + const string attribute = ".FriendlyAppName"; + string[] candidates = ["SPT.Launcher.exe", "SPT.Server.exe", "Aki.Launcher.exe"]; + + return mui + .GetValueNames() + .Where(v => candidates.Any(c => v.Contains($"{c}{attribute}", StringComparison.OrdinalIgnoreCase))) + .Select(v => Path.GetDirectoryName(v.Replace(attribute, string.Empty))) + .Distinct(); + } + catch + { + return []; + } + } + } +}