- Fixed selection duplicates caused by using differing-case installation directories as unique factors
- File and directory paths are now exact and correctly cased
This commit is contained in:
pointfeev 2023-05-31 18:33:46 -04:00
parent b63603a165
commit 1b1f0bf494
12 changed files with 31 additions and 28 deletions

View file

@ -4,7 +4,7 @@
<TargetFramework>net7.0-windows</TargetFramework> <TargetFramework>net7.0-windows</TargetFramework>
<UseWindowsForms>True</UseWindowsForms> <UseWindowsForms>True</UseWindowsForms>
<ApplicationIcon>Resources\ini.ico</ApplicationIcon> <ApplicationIcon>Resources\ini.ico</ApplicationIcon>
<Version>4.9.2</Version> <Version>4.9.3</Version>
<Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright> <Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright>
<Company>CreamInstaller</Company> <Company>CreamInstaller</Company>
<Product>Automatic DLC Unlocker Installer &amp; Configuration Generator</Product> <Product>Automatic DLC Unlocker Installer &amp; Configuration Generator</Product>

View file

@ -1,6 +1,5 @@
using System.ComponentModel; using System.ComponentModel;
using System.Windows.Forms; using System.Windows.Forms;
using CreamInstaller.Components; using CreamInstaller.Components;
namespace CreamInstaller.Forms namespace CreamInstaller.Forms

View file

@ -21,7 +21,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\Epic Games\EpicGamesLauncher", "AppDataPath", null) as string;
if (epicManifestsPath is not null && epicManifestsPath.EndsWith(@"\Data", StringComparison.Ordinal)) if (epicManifestsPath is not null && epicManifestsPath.EndsWith(@"\Data", StringComparison.Ordinal))
epicManifestsPath += @"\Manifests"; epicManifestsPath += @"\Manifests";
return epicManifestsPath.BeautifyPath(); return epicManifestsPath.ResolvePath();
} }
} }
@ -39,8 +39,7 @@ internal static class EpicLibrary
try try
{ {
Manifest manifest = JsonConvert.DeserializeObject<Manifest>(json); Manifest manifest = JsonConvert.DeserializeObject<Manifest>(json);
if (manifest is not null && !games.Any(g if (manifest is not null && games.All(g => g.CatalogNamespace != manifest.CatalogNamespace))
=> g.CatalogNamespace == manifest.CatalogNamespace && g.InstallLocation == manifest.InstallLocation))
games.Add(manifest); games.Add(manifest);
} }
catch catch

View file

@ -34,7 +34,7 @@ internal static class HeroicLibrary
{ {
DisplayName = appData.Title, CatalogNamespace = appData.Namespace, InstallLocation = appData.Install.InstallPath DisplayName = appData.Title, CatalogNamespace = appData.Namespace, InstallLocation = appData.Install.InstallPath
}; };
if (!games.Any(g => g.CatalogNamespace == manifest.CatalogNamespace && g.InstallLocation == manifest.InstallLocation)) if (games.All(g => g.CatalogNamespace != manifest.CatalogNamespace))
games.Add(manifest); games.Add(manifest);
} }
catch catch

View file

@ -25,7 +25,7 @@ internal static class ParadoxLauncher
get get
{ {
installPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Paradox Interactive\Paradox Launcher v2", "LauncherInstallation", null) as string; installPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Paradox Interactive\Paradox Launcher v2", "LauncherInstallation", null) as string;
return installPath.BeautifyPath(); return installPath.ResolvePath();
} }
} }

View file

@ -17,7 +17,7 @@ internal static class SteamLibrary
{ {
installPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Valve\Steam", "SteamPath", null) as string; installPath ??= Registry.GetValue(@"HKEY_CURRENT_USER\Software\Valve\Steam", "SteamPath", null) as string;
installPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam", "InstallPath", null) as string; installPath ??= Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam", "InstallPath", null) as string;
return installPath.BeautifyPath(); return installPath.ResolvePath();
} }
} }
@ -31,7 +31,7 @@ internal static class SteamLibrary
if (Program.Canceled) if (Program.Canceled)
return games; return games;
foreach ((string appId, string name, string branch, int buildId, string gameDirectory) game in (await GetGamesFromLibraryDirectory( foreach ((string appId, string name, string branch, int buildId, string gameDirectory) game in (await GetGamesFromLibraryDirectory(
libraryDirectory)).Where(game => !games.Any(_game => _game.appId == game.appId && _game.gameDirectory == game.gameDirectory))) libraryDirectory)).Where(game => games.All(_game => _game.appId != game.appId)))
games.Add(game); games.Add(game);
} }
return games; return games;
@ -57,12 +57,8 @@ internal static class SteamLibrary
if (string.IsNullOrWhiteSpace(appId) || string.IsNullOrWhiteSpace(installdir) || string.IsNullOrWhiteSpace(name) if (string.IsNullOrWhiteSpace(appId) || string.IsNullOrWhiteSpace(installdir) || string.IsNullOrWhiteSpace(name)
|| string.IsNullOrWhiteSpace(buildId)) || string.IsNullOrWhiteSpace(buildId))
continue; continue;
string gameDirectory = (libraryDirectory + @"\common\" + installdir).BeautifyPath(); string gameDirectory = (libraryDirectory + @"\common\" + installdir).ResolvePath();
if (games.Any(g => g.appId == appId && g.gameDirectory == gameDirectory)) if (gameDirectory is null || !int.TryParse(appId, out int _) || !int.TryParse(buildId, out int buildIdInt) || games.Any(g => g.appId == appId))
continue;
if (!int.TryParse(appId, out int _))
continue;
if (!int.TryParse(buildId, out int buildIdInt))
continue; continue;
VToken userConfig = result.Value.GetChild("UserConfig"); VToken userConfig = result.Value.GetChild("UserConfig");
string branch = userConfig?.GetChild("BetaKey")?.ToString(); string branch = userConfig?.GetChild("BetaKey")?.ToString();
@ -108,4 +104,4 @@ internal static class SteamLibrary
} }
return gameDirectories; return gameDirectories;
}); });
} }

View file

@ -30,8 +30,8 @@ internal static class UbisoftLibrary
foreach (string gameId in installsKey.GetSubKeyNames()) foreach (string gameId in installsKey.GetSubKeyNames())
{ {
RegistryKey installKey = installsKey.OpenSubKey(gameId); RegistryKey installKey = installsKey.OpenSubKey(gameId);
string installDir = installKey?.GetValue("InstallDir")?.ToString()?.BeautifyPath(); string installDir = installKey?.GetValue("InstallDir")?.ToString()?.ResolvePath();
if (installDir is not null && !games.Any(g => g.gameId == gameId && g.gameDirectory == installDir)) if (installDir is not null && games.All(g => g.gameId != gameId))
games.Add((gameId, new DirectoryInfo(installDir).Name, installDir)); games.Add((gameId, new DirectoryInfo(installDir).Name, installDir));
} }
return games; return games;

View file

@ -522,8 +522,8 @@ internal static class Resources
private static bool IsCommonIncorrectExecutable(this string rootDirectory, string path) private static bool IsCommonIncorrectExecutable(this string rootDirectory, string path)
{ {
string subPath = path[rootDirectory.Length..].ToUpperInvariant().BeautifyPath(); string subPath = path[rootDirectory.Length..].ResolvePath();
return subPath.Contains("SETUP") || subPath.Contains("REDIST") || subPath.Contains("SUPPORT") return subPath is null || subPath.Contains("SETUP") || subPath.Contains("REDIST") || subPath.Contains("SUPPORT")
|| subPath.Contains("CRASH") && (subPath.Contains("PAD") || subPath.Contains("REPORT")) || subPath.Contains("HELPER") || subPath.Contains("CRASH") && (subPath.Contains("PAD") || subPath.Contains("REPORT")) || subPath.Contains("HELPER")
|| subPath.Contains("CEFPROCESS") || subPath.Contains("ZFGAMEBROWSER") || subPath.Contains("MONO") || subPath.Contains("PLUGINS") || subPath.Contains("CEFPROCESS") || subPath.Contains("ZFGAMEBROWSER") || subPath.Contains("MONO") || subPath.Contains("PLUGINS")
|| subPath.Contains("MODDING") || subPath.Contains("MOD") && subPath.Contains("MANAGER") || subPath.Contains("BATTLEYE") || subPath.Contains("MODDING") || subPath.Contains("MOD") && subPath.Contains("MANAGER") || subPath.Contains("BATTLEYE")
@ -540,8 +540,8 @@ internal static class Resources
{ {
if (Program.Canceled) if (Program.Canceled)
return null; return null;
string subDirectory = directory.BeautifyPath(); string subDirectory = directory.ResolvePath();
if (dllDirectories.Contains(subDirectory)) if (subDirectory is null || dllDirectories.Contains(subDirectory))
continue; continue;
bool koaloaderInstalled = Koaloader.AutoLoadDLLs.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll)) bool koaloaderInstalled = Koaloader.AutoLoadDLLs.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
.Any(pair => pair.path.FileExists() && pair.path.IsResourceFile()); .Any(pair => pair.path.FileExists() && pair.path.IsResourceFile());

View file

@ -103,8 +103,7 @@ internal sealed class Selection : IEquatable<Selection>
} }
} }
public bool Equals(Selection other) public bool Equals(Selection other) => other is not null && (ReferenceEquals(this, other) || Id == other.Id && Platform == other.Platform);
=> other is not null && (ReferenceEquals(this, other) || Id == other.Id && Platform == other.Platform && RootDirectory == other.RootDirectory);
internal static Selection GetOrCreate(Platform platform, string id, string name, string rootDirectory, HashSet<string> dllDirectories, internal static Selection GetOrCreate(Platform platform, string id, string name, string rootDirectory, HashSet<string> dllDirectories,
List<(string directory, BinaryType binaryType)> executableDirectories) List<(string directory, BinaryType binaryType)> executableDirectories)
@ -150,5 +149,5 @@ internal sealed class Selection : IEquatable<Selection>
public override bool Equals(object obj) => ReferenceEquals(this, obj) || obj is Selection other && Equals(other); public override bool Equals(object obj) => ReferenceEquals(this, obj) || obj is Selection other && Equals(other);
public override int GetHashCode() => HashCode.Combine(Id, (int)Platform, RootDirectory); public override int GetHashCode() => HashCode.Combine(Id, (int)Platform);
} }

View file

@ -42,5 +42,15 @@ internal static class Diagnostics
internal static void OpenUrlInInternetBrowser(string url) => Process.Start(new ProcessStartInfo { FileName = url, UseShellExecute = true }); internal static void OpenUrlInInternetBrowser(string url) => Process.Start(new ProcessStartInfo { FileName = url, UseShellExecute = true });
internal static string BeautifyPath(this string path) => path is null ? null : Path.TrimEndingDirectorySeparator(Path.GetFullPath(path)).ToLowerInvariant(); internal static string ResolvePath(this string path)
} {
if (path is null || !path.FileExists() && !path.DirectoryExists())
return null;
DirectoryInfo info = new(path);
if (info.Parent is null)
return info.Name.ToUpperInvariant();
string parent = ResolvePath(info.Parent.FullName);
string name = info.Parent.GetFileSystemInfos(info.Name)[0].Name;
return parent is null ? name : Path.Combine(parent, name);
}
}

View file

@ -251,7 +251,7 @@ internal static class SafeIO
private static DialogResult IOWarnInternal(this string filePath, string message, Exception e, Form form = null) private static DialogResult IOWarnInternal(this string filePath, string message, Exception e, Form form = null)
{ {
using DialogForm dialogForm = new(form); using DialogForm dialogForm = new(form);
string description = message + ": " + filePath.BeautifyPath() + "\n\n"; string description = message + ": " + filePath.ResolvePath() + "\n\n";
if (e is IOException && (e.HResult & 0x0000FFFF) == 225) // virus or potentially unwanted software if (e is IOException && (e.HResult & 0x0000FFFF) == 225) // virus or potentially unwanted software
description += "Please resolve your anti-virus and press retry to continue . . . "; description += "Please resolve your anti-virus and press retry to continue . . . ";
else else

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 23 KiB