- Consolidated and vastly improved the performance of the program's methods of gathering game executables and DLLs
- Koaloader's respective unlocker DLLs are now correctly deployed based on executable bitnesses instead of which API DLLs exist
This commit is contained in:
pointfeev 2022-08-28 07:40:53 -04:00
parent 5bb7f1cd65
commit 9f2f0c176d
10 changed files with 175 additions and 240 deletions

View file

@ -23,7 +23,7 @@ internal class ContextMenuItem : ToolStripMenuItem
{
case "Paradox Launcher":
if (Directory.Exists(ParadoxLauncher.InstallPath))
foreach (string file in Directory.GetFiles(ParadoxLauncher.InstallPath, "*.exe"))
foreach (string file in Directory.EnumerateFiles(ParadoxLauncher.InstallPath, "*.exe"))
{
image = IconGrabber.GetFileIconImage(file);
break;

View file

@ -5,7 +5,7 @@
<UseWindowsForms>True</UseWindowsForms>
<ApplicationIcon>Resources\ini.ico</ApplicationIcon>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
<Version>4.1.0.0</Version>
<Version>4.1.1.0</Version>
<PackageIcon>Resources\ini.ico</PackageIcon>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright>

View file

@ -5,7 +5,6 @@ using Microsoft.Win32;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
@ -37,8 +36,7 @@ internal static class EpicLibrary
List<Manifest> games = new();
string manifests = EpicManifestsPath;
if (!Directory.Exists(manifests)) return games;
string[] files = Directory.GetFiles(manifests, "*.item");
foreach (string file in files)
foreach (string file in Directory.EnumerateFiles(manifests, "*.item"))
{
if (Program.Canceled) return games;
string json = File.ReadAllText(file);
@ -52,29 +50,4 @@ internal static class EpicLibrary
}
return games;
});
internal static async Task<List<string>> GetDllDirectoriesFromGameDirectory(string gameDirectory) => await Task.Run(async () =>
{
List<string> dllDirectories = new();
if (Program.Canceled || !Directory.Exists(gameDirectory)) return null;
gameDirectory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
if (File.Exists(api32)
|| File.Exists(api32_o)
|| File.Exists(api64)
|| File.Exists(api64_o)
|| File.Exists(config))
dllDirectories.Add(gameDirectory.BeautifyPath());
string[] directories = Directory.GetDirectories(gameDirectory);
foreach (string _directory in directories)
{
if (Program.Canceled) return null;
try
{
List<string> moreDllDirectories = await GetDllDirectoriesFromGameDirectory(_directory);
if (moreDllDirectories is not null) dllDirectories.AddRange(moreDllDirectories);
}
catch { }
}
return !dllDirectories.Any() ? null : dllDirectories;
});
}

View file

@ -109,14 +109,8 @@ internal partial class SelectForm : CustomForm
List<Task> appTasks = new();
if (ProgramsToScan.Any(c => c.platform is Platform.Paradox))
{
List<string> steamDllDirectories = await SteamLibrary.GetDllDirectoriesFromGameDirectory(ParadoxLauncher.InstallPath);
List<string> epicDllDirectories = await EpicLibrary.GetDllDirectoriesFromGameDirectory(ParadoxLauncher.InstallPath);
List<string> dllDirectories = new();
if (steamDllDirectories is not null)
dllDirectories = dllDirectories.Union(steamDllDirectories).ToList();
if (epicDllDirectories is not null)
dllDirectories = dllDirectories.Union(epicDllDirectories).ToList();
if (steamDllDirectories is not null || epicDllDirectories is not null)
List<string> dllDirectories = await ParadoxLauncher.InstallPath.GetDllDirectoriesFromGameDirectory(Platform.Paradox);
if (dllDirectories is not null)
{
ProgramSelection selection = ProgramSelection.FromPlatformId(Platform.Paradox, "PL");
selection ??= new();
@ -155,7 +149,7 @@ internal partial class SelectForm : CustomForm
Task task = Task.Run(async () =>
{
if (Program.Canceled) return;
List<string> dllDirectories = await SteamLibrary.GetDllDirectoriesFromGameDirectory(gameDirectory);
List<string> dllDirectories = await gameDirectory.GetDllDirectoriesFromGameDirectory(Platform.Steam);
if (dllDirectories is null)
{
Interlocked.Decrement(ref steamGamesToCheck);
@ -296,7 +290,7 @@ internal partial class SelectForm : CustomForm
Task task = Task.Run(async () =>
{
if (Program.Canceled) return;
List<string> dllDirectories = await EpicLibrary.GetDllDirectoriesFromGameDirectory(directory);
List<string> dllDirectories = await directory.GetDllDirectoriesFromGameDirectory(Platform.Epic);
if (dllDirectories is null)
{
RemoveFromRemainingGames(name);
@ -410,7 +404,7 @@ internal partial class SelectForm : CustomForm
Task task = Task.Run(async () =>
{
if (Program.Canceled) return;
List<string> dllDirectories = await UbisoftLibrary.GetDllDirectoriesFromGameDirectory(gameDirectory);
List<string> dllDirectories = await gameDirectory.GetDllDirectoriesFromGameDirectory(Platform.Ubisoft);
if (dllDirectories is null)
{
RemoveFromRemainingGames(name);

View file

@ -165,107 +165,84 @@ internal static class Koaloader
path.WriteProxy(selection.KoaloaderProxy, binaryType);
if (installForm is not null)
installForm.UpdateUser($"Wrote {(binaryType == BinaryType.BIT32 ? "32-bit" : "64-bit")} Koaloader: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
bool bit32 = false, bit64 = false;
foreach (string executable in Directory.EnumerateFiles(directory, "*.exe"))
if (executable.TryGetFileBinaryType(out BinaryType binaryType))
{
if (binaryType == BinaryType.BIT32)
bit32 = true;
else if (binaryType == BinaryType.BIT64)
bit64 = true;
if (bit32 && bit64)
break;
}
if (selection.Platform is Platform.Steam or Platform.Paradox)
{
bool did32 = false, did64 = false;
foreach (string dllDirectory in selection.DllDirectories)
if (bit32)
{
dllDirectory.GetSmokeApiComponents(out string api32, out _, out string api64, out _, out _, out _);
if (!did32 && File.Exists(api32))
{
did32 = true;
path = directory + @"\SmokeAPI32.dll";
"SmokeAPI.steam_api.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote SmokeAPI: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (!did64 && File.Exists(api64))
if (bit64)
{
did64 = true;
path = directory + @"\SmokeAPI64.dll";
"SmokeAPI.steam_api64.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote SmokeAPI: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (did32 && did64)
break;
}
if (did32 || did64)
SmokeAPI.CheckConfig(directory, selection, installForm);
}
if (selection.Platform is Platform.Epic or Platform.Paradox)
{
bool did32 = false, did64 = false;
foreach (string dllDirectory in selection.DllDirectories)
if (bit32)
{
dllDirectory.GetScreamApiComponents(out string api32, out _, out string api64, out _, out _);
if (!did32 && File.Exists(api32))
{
did32 = true;
path = directory + @"\ScreamAPI32.dll";
"ScreamAPI.EOSSDK-Win32-Shipping.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote ScreamAPI: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (!did64 && File.Exists(api64))
if (bit64)
{
did64 = true;
path = directory + @"\ScreamAPI64.dll";
"ScreamAPI.EOSSDK-Win64-Shipping.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote ScreamAPI: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (did32 && did64)
break;
}
if (did32 || did64)
ScreamAPI.CheckConfig(directory, selection, installForm);
}
if (selection.Platform is Platform.Ubisoft)
{
bool did32r1 = false, did64r1 = false, did32r2 = false, did64r2 = false;
foreach (string dllDirectory in selection.DllDirectories)
if (bit32)
{
dllDirectory.GetUplayR1Components(out string api32, out _, out string api64, out _, out _);
if (!did32r1 && File.Exists(api32))
{
did32r1 = true;
path = directory + @"\UplayR1Unlocker32.dll";
"UplayR1.uplay_r1_loader.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote Uplay R1 Unlocker: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (!did64r1 && File.Exists(api64))
if (bit64)
{
did64r1 = true;
path = directory + @"\UplayR1Unlocker64.dll";
"UplayR1.uplay_r1_loader64.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote Uplay R1 Unlocker: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
dllDirectory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out _, out api64, out _, out _);
if (!did32r2 && (File.Exists(old_api32) || File.Exists(old_api32)))
UplayR1.CheckConfig(directory, selection, installForm);
if (bit32)
{
did32r2 = true;
path = directory + @"\UplayR2Unlocker32.dll";
"UplayR2.upc_r2_loader.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote Uplay R2 Unlocker: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (!did64r2 && (File.Exists(old_api64) || File.Exists(api64)))
if (bit64)
{
did64r2 = true;
path = directory + @"\UplayR2Unlocker64.dll";
"UplayR2.upc_r2_loader64.dll".Write(path);
if (installForm is not null)
installForm.UpdateUser($"Wrote Uplay R2 Unlocker: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
}
if (did32r1 && did64r1 && did32r2 && did64r2)
break;
}
if (did32r1 || did64r1)
UplayR1.CheckConfig(directory, selection, installForm);
if (did32r2 || did64r2)
UplayR2.CheckConfig(directory, selection, installForm);
}
if (generateConfig)

View file

@ -77,22 +77,21 @@ internal static class Resources
private static extern bool GetBinaryType(string lpApplicationName, out BinaryType lpBinaryType);
internal static bool TryGetFileBinaryType(this string path, out BinaryType binaryType) => GetBinaryType(path, out binaryType);
internal static bool IsCommonIncorrectExecutable(this string rootDirectory, string path)
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(this string rootDirectory, bool filterCommon = false, Func<string, bool> validFunc = null) =>
await Task.Run(async () => (await rootDirectory.GetExecutables(filterCommon: filterCommon, validFunc: validFunc) ?? await rootDirectory.GetExecutables()).Select(e =>
{
string subPath = path[rootDirectory.Length..].ToUpperInvariant().BeautifyPath();
return subPath.Contains("SETUP") || subPath.Contains("REDIST")
|| subPath.Contains("CRASH") && (subPath.Contains("PAD") || subPath.Contains("REPORT"));
}
e.path = Path.GetDirectoryName(e.path);
return e;
}).DistinctBy(e => e.path).ToList());
internal static async Task<List<(string path, BinaryType binaryType)>> GetExecutables(this string rootDirectory, string subDirectory = null, bool filterCommon = false, Func<string, bool> validFunc = null) =>
await Task.Run(async () =>
internal static async Task<List<(string path, BinaryType binaryType)>> GetExecutables(this string rootDirectory, bool filterCommon = false, Func<string, bool> validFunc = null) => await Task.Run(() =>
{
List<(string path, BinaryType binaryType)> executables = new();
if (Program.Canceled || !Directory.Exists(subDirectory ?? rootDirectory)) return null;
Thread.Sleep(0);
string[] files = Directory.GetFiles(subDirectory ?? rootDirectory, "*.exe");
if (Program.Canceled || !Directory.Exists(rootDirectory)) return null;
List<string> files = new(Directory.EnumerateFiles(rootDirectory, "*.exe", new EnumerationOptions() { RecurseSubdirectories = true }));
foreach (string path in files)
{
if (Program.Canceled) return null;
Thread.Sleep(0);
if (!executables.Any(e => e.path == path)
&& (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
@ -102,6 +101,7 @@ internal static class Resources
}
foreach (string path in files)
{
if (Program.Canceled) return null;
Thread.Sleep(0);
if (!executables.Any(e => e.path == path)
&& (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
@ -109,28 +109,68 @@ internal static class Resources
&& path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT32)
executables.Add((path, binaryType));
}
string[] directories = Directory.GetDirectories(subDirectory ?? rootDirectory);
foreach (string directory in directories)
{
if (Program.Canceled) return null;
Thread.Sleep(0);
try
{
List<(string path, BinaryType binaryType)> moreExecutables = await rootDirectory.GetExecutables(directory, filterCommon, validFunc);
if (moreExecutables is not null)
executables.AddRange(moreExecutables);
}
catch { }
}
return !executables.Any() ? null : executables;
});
internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(this string rootDirectory, bool filterCommon = false, Func<string, bool> validFunc = null) =>
await Task.Run(async () => (await rootDirectory.GetExecutables(filterCommon: filterCommon, validFunc: validFunc) ?? await rootDirectory.GetExecutables()).Select(e =>
internal static bool IsCommonIncorrectExecutable(this string rootDirectory, string path)
{
e.path = Path.GetDirectoryName(e.path);
return e;
}).DistinctBy(e => e.path).ToList());
string subPath = path[rootDirectory.Length..].ToUpperInvariant().BeautifyPath();
return subPath.Contains("SETUP") || subPath.Contains("REDIST")
|| subPath.Contains("CRASH") && (subPath.Contains("PAD") || subPath.Contains("REPORT"));
}
internal static async Task<List<string>> GetDllDirectoriesFromGameDirectory(this string gameDirectory, Platform platform, List<string> dllDirectories = null) => await Task.Run(() =>
{
dllDirectories ??= new();
if (Program.Canceled || !Directory.Exists(gameDirectory)) return null;
List<string> directories = new(Directory.EnumerateDirectories(gameDirectory, "*", new EnumerationOptions() { RecurseSubdirectories = true })) { gameDirectory };
foreach (string subDirectory in directories)
{
if (Program.Canceled) return null;
Thread.Sleep(0);
if (platform is Platform.Steam or Platform.Paradox)
{
subDirectory.GetSmokeApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string config, out string cache);
if (File.Exists(api)
|| File.Exists(api_o)
|| File.Exists(api64)
|| File.Exists(api64_o)
|| File.Exists(config)
|| File.Exists(cache))
dllDirectories.Add(subDirectory.BeautifyPath());
}
if (platform is Platform.Epic or Platform.Paradox)
{
subDirectory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
if (File.Exists(api32)
|| File.Exists(api32_o)
|| File.Exists(api64)
|| File.Exists(api64_o)
|| File.Exists(config))
dllDirectories.Add(subDirectory.BeautifyPath());
}
if (platform is Platform.Ubisoft)
{
subDirectory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
if (File.Exists(api32)
|| File.Exists(api32_o)
|| File.Exists(api64)
|| File.Exists(api64_o)
|| File.Exists(config))
dllDirectories.Add(subDirectory.BeautifyPath());
subDirectory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config);
if (File.Exists(old_api32)
|| File.Exists(old_api64)
|| File.Exists(api32)
|| File.Exists(api32_o)
|| File.Exists(api64)
|| File.Exists(api64_o)
|| File.Exists(config))
dllDirectories.Add(subDirectory.BeautifyPath());
}
}
return !dllDirectories.Any() ? null : new List<string>(dllDirectories.Distinct());
});
internal static void GetCreamApiComponents(
this string directory,

View file

@ -156,15 +156,15 @@ internal static class SteamCMD
try
{
if (Directory.Exists(ConfigPath))
foreach (string file in Directory.GetFiles(ConfigPath, "*.tmp"))
foreach (string file in Directory.EnumerateFiles(ConfigPath, "*.tmp"))
File.Delete(file);
foreach (string file in Directory.GetFiles(DirectoryPath, "*.old"))
foreach (string file in Directory.EnumerateFiles(DirectoryPath, "*.old"))
File.Delete(file);
foreach (string file in Directory.GetFiles(DirectoryPath, "*.delete"))
foreach (string file in Directory.EnumerateFiles(DirectoryPath, "*.delete"))
File.Delete(file);
foreach (string file in Directory.GetFiles(DirectoryPath, "*.crash"))
foreach (string file in Directory.EnumerateFiles(DirectoryPath, "*.crash"))
File.Delete(file);
foreach (string file in Directory.GetFiles(DirectoryPath, "*.ntfs_transaction_failed"))
foreach (string file in Directory.EnumerateFiles(DirectoryPath, "*.ntfs_transaction_failed"))
File.Delete(file);
if (Directory.Exists(AppCachePath))
Directory.Delete(AppCachePath, true); // this is definitely needed, so SteamCMD gets the latest information for us

View file

@ -47,38 +47,11 @@ internal static class SteamLibrary
return games;
});
internal static async Task<List<string>> GetDllDirectoriesFromGameDirectory(string gameDirectory) => await Task.Run(async () =>
{
List<string> dllDirectories = new();
if (Program.Canceled || !Directory.Exists(gameDirectory)) return null;
gameDirectory.GetSmokeApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string config, out string cache);
if (File.Exists(api)
|| File.Exists(api_o)
|| File.Exists(api64)
|| File.Exists(api64_o)
|| File.Exists(config)
|| File.Exists(cache))
dllDirectories.Add(gameDirectory.BeautifyPath());
string[] directories = Directory.GetDirectories(gameDirectory);
foreach (string _directory in directories)
{
if (Program.Canceled) return null;
try
{
List<string> moreDllDirectories = await GetDllDirectoriesFromGameDirectory(_directory);
if (moreDllDirectories is not null) dllDirectories.AddRange(moreDllDirectories);
}
catch { }
}
return !dllDirectories.Any() ? null : dllDirectories;
});
internal static async Task<List<(string appId, string name, string branch, int buildId, string gameDirectory)>> GetGamesFromLibraryDirectory(string libraryDirectory) => await Task.Run(() =>
{
List<(string appId, string name, string branch, int buildId, string gameDirectory)> games = new();
if (Program.Canceled || !Directory.Exists(libraryDirectory)) return null;
string[] files = Directory.GetFiles(libraryDirectory, "*.acf");
foreach (string file in files)
foreach (string file in Directory.EnumerateFiles(libraryDirectory, "*.acf"))
{
if (Program.Canceled) return null;
if (ValveDataFile.TryDeserialize(File.ReadAllText(file, Encoding.UTF8), out VProperty result))

View file

@ -41,6 +41,7 @@ internal static class SteamStore
{
IDictionary<string, JToken> apps = (IDictionary<string, JToken>)JsonConvert.DeserializeObject(response);
if (apps is not null)
{
foreach (KeyValuePair<string, JToken> app in apps)
{
try
@ -77,6 +78,21 @@ internal static class SteamStore
#endif
}
}
#if DEBUG
else
{
using DialogForm dialogForm = new(null);
dialogForm.Show(SystemIcons.Error, "Response deserialization null for appid: " + appId);
}
#endif
}
#if DEBUG
else
{
using DialogForm dialogForm = new(null);
dialogForm.Show(SystemIcons.Error, "Response null for appid: " + appId);
}
#endif
}
if (cachedExists)
{

View file

@ -5,7 +5,6 @@ using Microsoft.Win32;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using static CreamInstaller.Resources.Resources;
@ -42,41 +41,4 @@ internal static class UbisoftLibrary
}
return games;
});
internal static async Task<List<string>> GetDllDirectoriesFromGameDirectory(string gameDirectory) => await Task.Run(async () =>
{
List<string> dllDirectories = new();
if (Program.Canceled || !Directory.Exists(gameDirectory)) return null;
gameDirectory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
if (File.Exists(api32)
|| File.Exists(api32_o)
|| File.Exists(api64)
|| File.Exists(api64_o)
|| File.Exists(config))
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);
if (File.Exists(old_api32)
|| File.Exists(old_api64)
|| File.Exists(api32)
|| File.Exists(api32_o)
|| File.Exists(api64)
|| File.Exists(api64_o)
|| File.Exists(config))
dllDirectories.Add(gameDirectory.BeautifyPath());
}
string[] directories = Directory.GetDirectories(gameDirectory);
foreach (string _directory in directories)
{
if (Program.Canceled) return null;
try
{
List<string> moreDllDirectories = await GetDllDirectoriesFromGameDirectory(_directory);
if (moreDllDirectories is not null) dllDirectories.AddRange(moreDllDirectories);
}
catch { }
}
return !dllDirectories.Any() ? null : dllDirectories;
});
}