diff --git a/CreamInstaller/CreamInstaller.csproj b/CreamInstaller/CreamInstaller.csproj index fc66015..821a133 100644 --- a/CreamInstaller/CreamInstaller.csproj +++ b/CreamInstaller/CreamInstaller.csproj @@ -148,7 +148,7 @@ - + diff --git a/CreamInstaller/Epic/EpicLibrary.cs b/CreamInstaller/Epic/EpicLibrary.cs index 5190a82..32393a2 100644 --- a/CreamInstaller/Epic/EpicLibrary.cs +++ b/CreamInstaller/Epic/EpicLibrary.cs @@ -1,4 +1,5 @@ using CreamInstaller.Resources; +using CreamInstaller.Utility; using Microsoft.Win32; @@ -22,7 +23,7 @@ internal static class EpicLibrary epicManifestsPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Epic Games\EpicGamesLauncher", "AppDataPath", null) as string; epicManifestsPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Epic Games\EpicGamesLauncher", "AppDataPath", null) as string; if (epicManifestsPath is not null && epicManifestsPath.EndsWith(@"\Data")) epicManifestsPath += @"\Manifests"; - return epicManifestsPath; + return epicManifestsPath.BeautifyPath(); } } @@ -57,7 +58,7 @@ internal static class EpicLibrary || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config)) - dllDirectories.Add(gameDirectory); + dllDirectories.Add(gameDirectory.BeautifyPath()); string[] directories = Directory.GetDirectories(gameDirectory); foreach (string _directory in directories) { diff --git a/CreamInstaller/Epic/Manifest.cs b/CreamInstaller/Epic/Manifest.cs index 2942710..11044ea 100644 --- a/CreamInstaller/Epic/Manifest.cs +++ b/CreamInstaller/Epic/Manifest.cs @@ -6,6 +6,8 @@ public class Manifest public string InstallLocation { get; set; } + public string LaunchExecutable { get; set; } + public string CatalogNamespace { get; set; } public string CatalogItemId { get; set; } diff --git a/CreamInstaller/Forms/InstallForm.cs b/CreamInstaller/Forms/InstallForm.cs index ab69b12..2429471 100644 --- a/CreamInstaller/Forms/InstallForm.cs +++ b/CreamInstaller/Forms/InstallForm.cs @@ -65,7 +65,7 @@ internal partial class InstallForm : CustomForm } if (selection.Koaloader && !Uninstalling) { - foreach (string directory in await selection.GetKoaloaderDirectories()) + foreach (string directory in selection.ExecutableDirectories) { UpdateUser("Installing Koaloader to " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); await Koaloader.Install(directory, selection, this); @@ -75,7 +75,7 @@ internal partial class InstallForm : CustomForm { if (Uninstalling) { - foreach (string directory in await selection.GetKoaloaderDirectories()) + foreach (string directory in selection.ExecutableDirectories) { directory.GetKoaloaderComponents(out List proxies, out string config); if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(Resources.Resources.ResourceIdentifier.Koaloader)) diff --git a/CreamInstaller/Forms/MainForm.cs b/CreamInstaller/Forms/MainForm.cs index 94142b2..405f3dc 100644 --- a/CreamInstaller/Forms/MainForm.cs +++ b/CreamInstaller/Forms/MainForm.cs @@ -72,8 +72,8 @@ internal partial class MainForm : CustomForm if (checkForUpdatesResult.CanUpdate) { #endif - latestVersion = checkForUpdatesResult.LastVersion; - versions = checkForUpdatesResult.Versions; + latestVersion = checkForUpdatesResult.LastVersion; + versions = checkForUpdatesResult.Versions; #if !DEBUG } #endif diff --git a/CreamInstaller/Forms/SelectForm.cs b/CreamInstaller/Forms/SelectForm.cs index 24a3a6c..1e1191e 100644 --- a/CreamInstaller/Forms/SelectForm.cs +++ b/CreamInstaller/Forms/SelectForm.cs @@ -122,6 +122,7 @@ internal partial class SelectForm : CustomForm selection.Id = "PL"; selection.Name = "Paradox Launcher"; selection.RootDirectory = ParadoxLauncher.InstallPath; + selection.ExecutableDirectories = await selection.RootDirectory.GetExecutableDirectories(d => !d.Contains("bootstrapper")); selection.DllDirectories = dllDirectories; selection.Platform = Platform.Paradox; @@ -233,6 +234,16 @@ internal partial class SelectForm : CustomForm selection.Id = appId; selection.Name = appData?.name ?? name; selection.RootDirectory = gameDirectory; + selection.ExecutableDirectories = new(); + VToken launch = appInfo?.Value?.GetChild("config")?.GetChild("launch"); + if (launch is not null) + foreach (VToken token in launch.Children()) + if (token?.GetChild("executable")?.ToString() is string executable + && (selection.RootDirectory + @"\" + Path.GetDirectoryName(executable)).BeautifyPath() is string path + && !selection.ExecutableDirectories.Contains(path)) + selection.ExecutableDirectories.Add(path); + if (!selection.ExecutableDirectories.Any()) + selection.ExecutableDirectories.Add(selection.RootDirectory); selection.DllDirectories = dllDirectories; selection.Platform = Platform.Steam; selection.ProductUrl = "https://store.steampowered.com/app/" + appId; @@ -330,6 +341,11 @@ internal partial class SelectForm : CustomForm selection.Id = @namespace; selection.Name = name; selection.RootDirectory = directory; + selection.ExecutableDirectories = new(); + if (manifest.LaunchExecutable is string executable && (selection.RootDirectory + @"\" + Path.GetDirectoryName(executable)).BeautifyPath() is string path) + selection.ExecutableDirectories.Add(path); + else + selection.ExecutableDirectories.Add(selection.RootDirectory); selection.DllDirectories = dllDirectories; selection.Platform = Platform.Epic; foreach (KeyValuePair pair in entitlements.Where(p => p.Value.name == selection.Name)) @@ -411,6 +427,7 @@ internal partial class SelectForm : CustomForm selection.Id = gameId; selection.Name = name; selection.RootDirectory = gameDirectory; + selection.ExecutableDirectories = new() { selection.RootDirectory }; selection.DllDirectories = dllDirectories; selection.Platform = Platform.Ubisoft; selection.IconUrl = IconGrabber.GetDomainFaviconUrl("store.ubi.com"); diff --git a/CreamInstaller/Paradox/ParadoxLauncher.cs b/CreamInstaller/Paradox/ParadoxLauncher.cs index 6fa8162..8bb6797 100644 --- a/CreamInstaller/Paradox/ParadoxLauncher.cs +++ b/CreamInstaller/Paradox/ParadoxLauncher.cs @@ -22,7 +22,7 @@ internal static class ParadoxLauncher { installPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Paradox Interactive\Paradox Launcher v2", "LauncherInstallation", null) as string; installPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Wow6432Node\Paradox Interactive\Paradox Launcher v2", "LauncherInstallation", null) as string; - return installPath; + return installPath.BeautifyPath(); } } diff --git a/CreamInstaller/ProgramSelection.cs b/CreamInstaller/ProgramSelection.cs index 52016e3..964f954 100644 --- a/CreamInstaller/ProgramSelection.cs +++ b/CreamInstaller/ProgramSelection.cs @@ -4,7 +4,6 @@ using CreamInstaller.Resources; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Threading.Tasks; namespace CreamInstaller; @@ -43,6 +42,7 @@ internal class ProgramSelection internal string WebsiteUrl; internal string RootDirectory; + internal List ExecutableDirectories; internal List DllDirectories; internal readonly SortedList AllDlc = new(PlatformIdComparer.String); @@ -51,9 +51,6 @@ internal class ProgramSelection internal readonly List<(string id, string name, SortedList dlc)> ExtraDlc = new(); // for Paradox Launcher internal readonly List<(string id, string name, SortedList dlc)> ExtraSelectedDlc = new(); // for Paradox Launcher - private List koaloaderDirectories; - internal async Task> GetKoaloaderDirectories() => koaloaderDirectories ??= await RootDirectory.GetKoaloaderDirectories(); - internal bool AreDllsLocked { get diff --git a/CreamInstaller/Resources/Koaloader.cs b/CreamInstaller/Resources/Koaloader.cs index e883901..a8f4687 100644 --- a/CreamInstaller/Resources/Koaloader.cs +++ b/CreamInstaller/Resources/Koaloader.cs @@ -30,7 +30,7 @@ internal static class Koaloader { ("SmokeAPI", "SmokeAPI32.dll"), ("SmokeAPI", "SmokeAPI64.dll"), ("ScreamAPI", "ScreamAPI32.dll"), ("ScreamAPI", "ScreamAPI64.dll"), - ("Uplay R2 Unlocker", "UplayR2Unlocker32.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker64.dll"), + ("Uplay R1 Unlocker", "UplayR1Unlocker32.dll"), ("Uplay R1 Unlocker", "UplayR1Unlocker64.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker32.dll"), ("Uplay R2 Unlocker", "UplayR2Unlocker64.dll") }; @@ -43,8 +43,8 @@ internal static class Koaloader if (targets.Any()) { writer.WriteLine(" \"targets\": ["); - System.Collections.Generic.KeyValuePair lastTarget = targets.Last(); - foreach (System.Collections.Generic.KeyValuePair pair in targets) + KeyValuePair lastTarget = targets.Last(); + foreach (KeyValuePair pair in targets) { string path = pair.Value; writer.WriteLine($" \"{path}\"{(pair.Equals(lastTarget) ? "" : ",")}"); @@ -58,8 +58,8 @@ internal static class Koaloader if (modules.Any()) { writer.WriteLine(" \"modules\": ["); - System.Collections.Generic.KeyValuePair lastModule = modules.Last(); - foreach (System.Collections.Generic.KeyValuePair pair in modules) + KeyValuePair lastModule = modules.Last(); + foreach (KeyValuePair pair in modules) { string path = pair.Value; writer.WriteLine(" {"); @@ -76,27 +76,6 @@ internal static class Koaloader writer.WriteLine("}"); } - internal static async Task> GetKoaloaderDirectories(this string rootDirectory) => await Task.Run(async () => - { - List executableDirectories = new(); - if (Program.Canceled || !Directory.Exists(rootDirectory)) return null; - if (Directory.GetFiles(rootDirectory, "*.exe").Any()) - executableDirectories.Add(rootDirectory); - string[] directories = Directory.GetDirectories(rootDirectory); - foreach (string _directory in directories) - { - if (Program.Canceled) return null; - try - { - List moreExecutableDirectories = await _directory.GetKoaloaderDirectories(); - if (moreExecutableDirectories is not null) - executableDirectories.AddRange(moreExecutableDirectories); - } - catch { } - } - return !executableDirectories.Any() ? null : executableDirectories; - }); - internal static async Task Uninstall(string directory, InstallForm installForm = null, bool deleteConfig = true) => await Task.Run(() => { directory.GetKoaloaderComponents(out List proxies, out string config); diff --git a/CreamInstaller/Resources/Resources.cs b/CreamInstaller/Resources/Resources.cs index 2bfd539..3f02fc0 100644 --- a/CreamInstaller/Resources/Resources.cs +++ b/CreamInstaller/Resources/Resources.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Security.Cryptography; +using System.Threading.Tasks; namespace CreamInstaller.Resources; @@ -55,6 +56,27 @@ internal static class Resources return false; } + internal static async Task> GetExecutableDirectories(this string rootDirectory, Func validFunc = null) => await Task.Run(async () => + { + List executableDirectories = new(); + if (Program.Canceled || !Directory.Exists(rootDirectory)) return null; + if (Directory.GetFiles(rootDirectory, "*.exe").Any(d => validFunc(d))) + executableDirectories.Add(rootDirectory); + string[] directories = Directory.GetDirectories(rootDirectory); + foreach (string _directory in directories) + { + if (Program.Canceled) return null; + try + { + List moreExecutableDirectories = await _directory.GetExecutableDirectories(validFunc); + if (moreExecutableDirectories is not null) + executableDirectories.AddRange(moreExecutableDirectories); + } + catch { } + } + return !executableDirectories.Any() ? null : executableDirectories; + }); + internal static void GetCreamApiComponents( this string directory, out string api32, out string api32_o, diff --git a/CreamInstaller/Steam/SteamLibrary.cs b/CreamInstaller/Steam/SteamLibrary.cs index f660f69..f635459 100644 --- a/CreamInstaller/Steam/SteamLibrary.cs +++ b/CreamInstaller/Steam/SteamLibrary.cs @@ -1,4 +1,5 @@ using CreamInstaller.Resources; +using CreamInstaller.Utility; using Gameloop.Vdf.Linq; @@ -21,7 +22,7 @@ internal static class SteamLibrary { installPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam", "InstallPath", null) as string; installPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Valve\Steam", "InstallPath", null) as string; - return installPath; + return installPath.BeautifyPath(); } } @@ -52,7 +53,7 @@ internal static class SteamLibrary || File.Exists(api64_o) || File.Exists(config) || File.Exists(cache)) - dllDirectories.Add(gameDirectory); + dllDirectories.Add(gameDirectory.BeautifyPath()); string[] directories = Directory.GetDirectories(gameDirectory); foreach (string _directory in directories) { @@ -91,7 +92,7 @@ internal static class SteamLibrary string gameDirectory = libraryDirectory + @"\common\" + installdir; if (!int.TryParse(appId, out int appIdInt)) continue; if (!int.TryParse(buildId, out int buildIdInt)) continue; - games.Add((appId, name, branch, buildIdInt, gameDirectory)); + games.Add((appId, name, branch, buildIdInt, gameDirectory.BeautifyPath())); } } return !games.Any() ? null : games; diff --git a/CreamInstaller/Ubisoft/UbisoftLibrary.cs b/CreamInstaller/Ubisoft/UbisoftLibrary.cs index 1fc0d9d..a07142c 100644 --- a/CreamInstaller/Ubisoft/UbisoftLibrary.cs +++ b/CreamInstaller/Ubisoft/UbisoftLibrary.cs @@ -1,4 +1,5 @@ using CreamInstaller.Resources; +using CreamInstaller.Utility; using Microsoft.Win32; @@ -32,7 +33,7 @@ internal static class UbisoftLibrary RegistryKey installKey = installsKey.OpenSubKey(gameId); string installDir = installKey?.GetValue("InstallDir")?.ToString(); if (installDir is not null) - games.Add((gameId, new DirectoryInfo(installDir).Name, Path.GetFullPath(installDir))); + games.Add((gameId, new DirectoryInfo(installDir).Name, installDir.BeautifyPath())); } return games; }); @@ -47,7 +48,7 @@ internal static class UbisoftLibrary || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config)) - dllDirectories.Add(gameDirectory); + dllDirectories.Add(gameDirectory.BeautifyPath()); else { gameDirectory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config); @@ -58,7 +59,7 @@ internal static class UbisoftLibrary || File.Exists(api64) || File.Exists(api64_o) || File.Exists(config)) - dllDirectories.Add(gameDirectory); + dllDirectories.Add(gameDirectory.BeautifyPath()); } string[] directories = Directory.GetDirectories(gameDirectory); foreach (string _directory in directories) diff --git a/CreamInstaller/Utility/Diagnostics.cs b/CreamInstaller/Utility/Diagnostics.cs index b5caf8b..dcc03c4 100644 --- a/CreamInstaller/Utility/Diagnostics.cs +++ b/CreamInstaller/Utility/Diagnostics.cs @@ -57,4 +57,6 @@ internal static class Diagnostics FileName = url, UseShellExecute = true }); + + internal static string BeautifyPath(this string path) => path is null ? null : Path.TrimEndingDirectorySeparator(Path.GetFullPath(path)); }