- Executable bitness is now detected automatically per-directory (prioritizing 64-bit before 32-bit)
- Executables which or not 32-bit nor 64-bit are now omitted
- Saved pre-v4.1.0.0 proxy choices will be automatically converted to the new format ("Koaloader.version_64.version.dll" -> "version")
- Executable directories' determined bitness can be visualized with the context menu (or during installation)
This commit is contained in:
pointfeev 2022-08-27 22:04:42 -04:00
parent 0fe30cd966
commit 50c5f4fb24
12 changed files with 149 additions and 105 deletions

View file

@ -8,6 +8,8 @@ using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Forms.VisualStyles; using System.Windows.Forms.VisualStyles;
using static CreamInstaller.Resources.Resources;
using TreeView = System.Windows.Forms.TreeView; using TreeView = System.Windows.Forms.TreeView;
namespace CreamInstaller.Components; namespace CreamInstaller.Components;
@ -157,7 +159,7 @@ internal class CustomTreeView : TreeView
comboBoxFont ??= new(font.FontFamily, 6, font.Style, font.Unit, font.GdiCharSet, font.GdiVerticalFont); comboBoxFont ??= new(font.FontFamily, 6, font.Style, font.Unit, font.GdiCharSet, font.GdiVerticalFont);
ComboBoxState comboBoxState = Enabled ? ComboBoxState.Normal : ComboBoxState.Disabled; ComboBoxState comboBoxState = Enabled ? ComboBoxState.Normal : ComboBoxState.Disabled;
text = selection.KoaloaderProxy.GetKoaloaderProxyDisplay(); text = selection.KoaloaderProxy + ".dll";
size = TextRenderer.MeasureText(graphics, text, comboBoxFont) + new Size(6, 0); size = TextRenderer.MeasureText(graphics, text, comboBoxFont) + new Size(6, 0);
int padding = 2; int padding = 2;
bounds = new(bounds.X + bounds.Width, bounds.Y + padding / 2, size.Width, bounds.Height - padding); bounds = new(bounds.X + bounds.Width, bounds.Y + padding / 2, size.Width, bounds.Height - padding);
@ -210,50 +212,25 @@ internal class CustomTreeView : TreeView
_ = comboBoxBounds.Remove(pair.Key); _ = comboBoxBounds.Remove(pair.Key);
else if (pair.Value.Contains(clickPoint)) else if (pair.Value.Contains(clickPoint))
{ {
List<string> proxies = Resources.Resources.EmbeddedResources.FindAll(r => r.StartsWith("Koaloader")); List<string> proxies = EmbeddedResources.FindAll(r => r.StartsWith("Koaloader"))
.Select(p =>
{
p.GetProxyInfoFromIdentifier(out string proxyName, out _);
return proxyName;
}).Distinct().ToList();
comboBoxDropDown ??= new(); comboBoxDropDown ??= new();
comboBoxDropDown.ShowItemToolTips = false; comboBoxDropDown.ShowItemToolTips = false;
comboBoxDropDown.Items.Clear(); comboBoxDropDown.Items.Clear();
_ = comboBoxDropDown.Items.Add(new ToolStripButton("32-bit", null, (s, e) => foreach (string proxy in proxies)
{ {
comboBoxDropDown.Items.Clear(); _ = comboBoxDropDown.Items.Add(new ToolStripButton(proxy + ".dll", null, (s, e) =>
foreach (string proxy in proxies)
{ {
string text = proxy.GetKoaloaderProxyDisplay(); pair.Key.KoaloaderProxy = proxy;
if (text.Contains("32-bit")) ProgramData.UpdateKoaloaderProxyChoices();
{ Invalidate();
_ = comboBoxDropDown.Items.Add(new ToolStripButton(text, null, new EventHandler((sender, e) => })
{ { Font = comboBoxFont });
pair.Key.KoaloaderProxy = proxy; }
ProgramData.UpdateKoaloaderProxyChoices();
Invalidate();
}))
{ Font = comboBoxFont });
}
}
comboBoxDropDown.Show(new(comboBoxDropDown.Left, comboBoxDropDown.Top));
})
{ Font = comboBoxFont });
_ = comboBoxDropDown.Items.Add(new ToolStripButton("64-bit", null, (s, e) =>
{
comboBoxDropDown.Items.Clear();
foreach (string proxy in proxies)
{
string text = proxy.GetKoaloaderProxyDisplay();
if (text.Contains("64-bit"))
{
_ = comboBoxDropDown.Items.Add(new ToolStripButton(text, null, new EventHandler((sender, e) =>
{
pair.Key.KoaloaderProxy = proxy;
ProgramData.UpdateKoaloaderProxyChoices();
Invalidate();
}))
{ Font = comboBoxFont });
}
}
comboBoxDropDown.Show(new(comboBoxDropDown.Left, comboBoxDropDown.Top));
})
{ Font = comboBoxFont });
comboBoxDropDown.Show(this, PointToScreen(new(pair.Value.Left, pair.Value.Bottom - 1))); comboBoxDropDown.Show(this, PointToScreen(new(pair.Value.Left, pair.Value.Bottom - 1)));
invalidate = true; invalidate = true;
break; break;

View file

@ -5,7 +5,7 @@
<UseWindowsForms>True</UseWindowsForms> <UseWindowsForms>True</UseWindowsForms>
<ApplicationIcon>Resources\ini.ico</ApplicationIcon> <ApplicationIcon>Resources\ini.ico</ApplicationIcon>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract> <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
<Version>4.0.2.1</Version> <Version>4.1.0.0</Version>
<PackageIcon>Resources\ini.ico</PackageIcon> <PackageIcon>Resources\ini.ico</PackageIcon>
<PackageLicenseFile>LICENSE</PackageLicenseFile> <PackageLicenseFile>LICENSE</PackageLicenseFile>
<Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright> <Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright>
@ -151,6 +151,7 @@
<PackageReference Include="HtmlAgilityPack" Version="1.11.45" /> <PackageReference Include="HtmlAgilityPack" Version="1.11.45" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Onova" Version="2.6.2" /> <PackageReference Include="Onova" Version="2.6.2" />
<PackageReference Include="System.Reflection.Metadata" Version="6.0.1" />
<PackageReference Include="System.ServiceModel.Primitives" Version="4.10.0" /> <PackageReference Include="System.ServiceModel.Primitives" Version="4.10.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -9,6 +9,8 @@ using System.Linq;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using static CreamInstaller.Resources.Resources;
namespace CreamInstaller.Epic; namespace CreamInstaller.Epic;
internal static class EpicLibrary internal static class EpicLibrary
@ -27,7 +29,7 @@ internal static class EpicLibrary
} }
} }
internal static async Task<List<string>> GetExecutableDirectories(string gameDirectory) => internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(string gameDirectory) =>
await Task.Run(async () => await gameDirectory.GetExecutableDirectories(filterCommon: true)); await Task.Run(async () => await gameDirectory.GetExecutableDirectories(filterCommon: true));
internal static async Task<List<Manifest>> GetGames() => await Task.Run(() => internal static async Task<List<Manifest>> GetGames() => await Task.Run(() =>

View file

@ -12,6 +12,7 @@ using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using static CreamInstaller.Paradox.ParadoxLauncher; using static CreamInstaller.Paradox.ParadoxLauncher;
using static CreamInstaller.Resources.Resources;
namespace CreamInstaller; namespace CreamInstaller;
@ -64,13 +65,16 @@ internal partial class InstallForm : CustomForm
UpdateUser($"Repairing Paradox Launcher . . . ", InstallationLog.Operation); UpdateUser($"Repairing Paradox Launcher . . . ", InstallationLog.Operation);
_ = await Repair(this, selection); _ = await Repair(this, selection);
} }
IEnumerable<string> invalidDirectories = (await selection.RootDirectory.GetExecutables()).Where(d => !selection.ExecutableDirectories.Contains(d)); IEnumerable<string> invalidDirectories = (await selection.RootDirectory.GetExecutables())
if (!selection.ExecutableDirectories.Contains(selection.RootDirectory)) invalidDirectories = invalidDirectories.Append(selection.RootDirectory); .Where(d => !selection.ExecutableDirectories.Any(s => d.path.Contains(s.directory)))
.Select(d => Path.GetDirectoryName(d.path));
if (!selection.ExecutableDirectories.Any(s => s.directory == selection.RootDirectory))
invalidDirectories = invalidDirectories.Append(selection.RootDirectory);
invalidDirectories = invalidDirectories.Distinct(); invalidDirectories = invalidDirectories.Distinct();
foreach (string directory in invalidDirectories) foreach (string directory in invalidDirectories)
{ {
directory.GetKoaloaderComponents(out List<string> proxies, out string config); directory.GetKoaloaderComponents(out List<string> proxies, out string config);
if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(Resources.Resources.ResourceIdentifier.Koaloader)) if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
|| Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll)) || Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll))
|| File.Exists(config)) || File.Exists(config))
{ {
@ -81,10 +85,10 @@ internal partial class InstallForm : CustomForm
} }
if (Uninstalling || !selection.Koaloader) if (Uninstalling || !selection.Koaloader)
{ {
foreach (string directory in selection.ExecutableDirectories) foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories)
{ {
directory.GetKoaloaderComponents(out List<string> proxies, out string config); directory.GetKoaloaderComponents(out List<string> proxies, out string config);
if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(Resources.Resources.ResourceIdentifier.Koaloader)) if (proxies.Any(proxy => File.Exists(proxy) && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
|| Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll)) || Koaloader.AutoLoadDlls.Any(pair => File.Exists(directory + @"\" + pair.dll))
|| File.Exists(config)) || File.Exists(config))
{ {
@ -162,10 +166,10 @@ internal partial class InstallForm : CustomForm
} }
if (selection.Koaloader && !Uninstalling) if (selection.Koaloader && !Uninstalling)
{ {
foreach (string directory in selection.ExecutableDirectories) foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories)
{ {
UpdateUser("Installing Koaloader to " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); UpdateUser("Installing Koaloader to " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
await Koaloader.Install(directory, selection, this); await Koaloader.Install(directory, binaryType, selection, this);
} }
} }
UpdateProgress(100); UpdateProgress(100);

View file

@ -21,6 +21,8 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using static CreamInstaller.Resources.Resources;
namespace CreamInstaller; namespace CreamInstaller;
internal partial class SelectForm : CustomForm internal partial class SelectForm : CustomForm
@ -728,14 +730,13 @@ internal partial class SelectForm : CustomForm
contextMenuStrip.Items.Add(new ToolStripSeparator()); contextMenuStrip.Items.Add(new ToolStripSeparator());
contextMenuStrip.Items.Add(new ContextMenuItem("Open Root Directory", "File Explorer", contextMenuStrip.Items.Add(new ContextMenuItem("Open Root Directory", "File Explorer",
new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(selection.RootDirectory)))); new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(selection.RootDirectory))));
List<string> directories = selection.ExecutableDirectories.ToList();
int executables = 0; int executables = 0;
foreach (string directory in directories) foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories.ToList())
{ {
contextMenuStrip.Items.Add(new ContextMenuItem($"Open Executable Directory #{++executables}", "File Explorer", contextMenuStrip.Items.Add(new ContextMenuItem($"Open Executable Directory #{++executables} ({(binaryType == BinaryType.BIT32 ? "32" : "64")}-bit)", "File Explorer",
new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory)))); new EventHandler((sender, e) => Diagnostics.OpenDirectoryInFileExplorer(directory))));
} }
directories = selection.DllDirectories.ToList(); List<string> directories = selection.DllDirectories.ToList();
int steam = 0, epic = 0, r1 = 0, r2 = 0; int steam = 0, epic = 0, r1 = 0, r2 = 0;
if (selection.Platform is Platform.Steam or Platform.Paradox) if (selection.Platform is Platform.Steam or Platform.Paradox)
foreach (string directory in directories) foreach (string directory in directories)

View file

@ -27,8 +27,8 @@ internal static class ParadoxLauncher
} }
} }
internal static async Task<List<string>> GetExecutableDirectories(string gameDirectory) => internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(string gameDirectory) =>
await Task.Run(async () => await gameDirectory.GetExecutableDirectories(validFunc: d => !Path.GetFileName(d).Contains("bootstrapper"))); await Task.Run(async () => await gameDirectory.GetExecutableDirectories(validFunc: path => !Path.GetFileName(path).Contains("bootstrapper")));
private static void PopulateDlc(ProgramSelection paradoxLauncher = null) private static void PopulateDlc(ProgramSelection paradoxLauncher = null)
{ {

View file

@ -5,6 +5,8 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using static CreamInstaller.Resources.Resources;
namespace CreamInstaller; namespace CreamInstaller;
public enum Platform public enum Platform
@ -43,7 +45,7 @@ internal class ProgramSelection
internal string WebsiteUrl; internal string WebsiteUrl;
internal string RootDirectory; internal string RootDirectory;
internal List<string> ExecutableDirectories; internal List<(string directory, BinaryType binaryType)> ExecutableDirectories;
internal List<string> DllDirectories; internal List<string> DllDirectories;
internal readonly SortedList<string, (DlcType type, string name, string icon)> AllDlc = new(PlatformIdComparer.String); internal readonly SortedList<string, (DlcType type, string name, string icon)> AllDlc = new(PlatformIdComparer.String);

View file

@ -7,6 +7,8 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using static CreamInstaller.Resources.Resources;
namespace CreamInstaller.Resources; namespace CreamInstaller.Resources;
internal static class Koaloader internal static class Koaloader
@ -18,7 +20,7 @@ internal static class Koaloader
) )
{ {
proxies = new(); proxies = new();
foreach (string proxy in Resources.EmbeddedResources.Select(proxy => foreach (string proxy in EmbeddedResources.Select(proxy =>
{ {
proxy = proxy[(proxy.IndexOf('.') + 1)..]; proxy = proxy[(proxy.IndexOf('.') + 1)..];
return proxy[(proxy.IndexOf('.') + 1)..]; return proxy[(proxy.IndexOf('.') + 1)..];
@ -26,13 +28,26 @@ internal static class Koaloader
config = directory + @"\Koaloader.json"; config = directory + @"\Koaloader.json";
} }
internal static string GetKoaloaderProxyDisplay(this string proxy) internal static void WriteProxy(this string path, string proxyName, BinaryType binaryType)
{ {
string proxyDisplay = proxy[(proxy.IndexOf('.') + 1)..]; foreach (string resourceIdentifier in EmbeddedResources.FindAll(r => r.StartsWith("Koaloader")))
proxyDisplay = proxyDisplay[..proxyDisplay.IndexOf('.')]; {
string name = proxyDisplay[..proxyDisplay.LastIndexOf('_')]; resourceIdentifier.GetProxyInfoFromIdentifier(out string _proxyName, out BinaryType _binaryType);
string bitness = proxyDisplay[(proxyDisplay.LastIndexOf('_') + 1)..]; if (_proxyName == proxyName && _binaryType == binaryType)
return $"{name}.dll ({bitness}-bit)"; {
resourceIdentifier.Write(path);
break;
}
}
}
internal static void GetProxyInfoFromIdentifier(this string resourceIdentifier, out string proxyName, out BinaryType binaryType)
{
string baseIdentifier = resourceIdentifier[(resourceIdentifier.IndexOf('.') + 1)..];
baseIdentifier = baseIdentifier[..baseIdentifier.IndexOf('.')];
proxyName = baseIdentifier[..baseIdentifier.LastIndexOf('_')];
string bitness = baseIdentifier[(baseIdentifier.LastIndexOf('_') + 1)..];
binaryType = bitness == "32" ? BinaryType.BIT32 : bitness == "64" ? BinaryType.BIT64 : BinaryType.Unknown;
} }
internal static readonly List<(string unlocker, string dll)> AutoLoadDlls = new() internal static readonly List<(string unlocker, string dll)> AutoLoadDlls = new()
@ -137,22 +152,19 @@ internal static class Koaloader
await UplayR2.Uninstall(directory, installForm, deleteConfig); await UplayR2.Uninstall(directory, installForm, deleteConfig);
}); });
internal static async Task Install(string directory, ProgramSelection selection, InstallForm installForm = null, bool generateConfig = true) => await Task.Run(() => internal static async Task Install(string directory, BinaryType binaryType, ProgramSelection selection, InstallForm installForm = null, bool generateConfig = true) => await Task.Run(() =>
{ {
directory.GetKoaloaderComponents(out List<string> proxies, out string config); directory.GetKoaloaderComponents(out List<string> proxies, out string config);
string proxy = selection.KoaloaderProxy; string path = directory + @"\" + selection.KoaloaderProxy + ".dll";
proxy = proxy[(proxy.IndexOf('.') + 1)..]; foreach (string _path in proxies.Where(p => p != path && File.Exists(p) && p.IsResourceFile(ResourceIdentifier.Koaloader)))
proxy = proxy[(proxy.IndexOf('.') + 1)..];
string path = directory + @"\" + proxy;
foreach (string proxyPath in proxies.Where(proxyPath => proxyPath != path && File.Exists(proxyPath) && proxyPath.IsResourceFile(Resources.ResourceIdentifier.Koaloader)))
{ {
File.Delete(proxyPath); File.Delete(_path);
if (installForm is not null) if (installForm is not null)
installForm.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxyPath)}", InstallationLog.Action, info: false); installForm.UpdateUser($"Deleted Koaloader: {Path.GetFileName(_path)}", InstallationLog.Action, info: false);
} }
selection.KoaloaderProxy.Write(path); path.WriteProxy(selection.KoaloaderProxy, binaryType);
if (installForm is not null) if (installForm is not null)
installForm.UpdateUser($"Wrote Koaloader: {Path.GetFileName(path)}", InstallationLog.Action, info: false); installForm.UpdateUser($"Wrote {(binaryType == BinaryType.BIT32 ? "32-bit" : "64-bit")} Koaloader: {Path.GetFileName(path)}", InstallationLog.Action, info: false);
if (selection.Platform is Platform.Steam or Platform.Paradox) if (selection.Platform is Platform.Steam or Platform.Paradox)
{ {
bool did32 = false, did64 = false; bool did32 = false, did64 = false;

View file

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -29,9 +30,9 @@ internal static class Resources
} }
} }
internal static void Write(this string resourceName, string filePath) internal static void Write(this string resourceIdentifier, string filePath)
{ {
using Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("CreamInstaller.Resources." + resourceName); using Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("CreamInstaller.Resources." + resourceIdentifier);
using FileStream file = new(filePath, FileMode.Create, FileAccess.Write); using FileStream file = new(filePath, FileMode.Create, FileAccess.Write);
resource.CopyTo(file); resource.CopyTo(file);
} }
@ -59,6 +60,23 @@ internal static class Resources
return false; return false;
} }
internal enum BinaryType
{
Unknown = -1,
BIT32 = 0,
DOS = 1,
WOW = 2,
PIF = 3,
POSIX = 4,
OS216 = 5,
BIT64 = 6,
}
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
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 bool IsCommonIncorrectExecutable(this string rootDirectory, string path)
{ {
string subPath = path[rootDirectory.Length..].ToUpperInvariant().BeautifyPath(); string subPath = path[rootDirectory.Length..].ToUpperInvariant().BeautifyPath();
@ -66,35 +84,53 @@ internal static class Resources
|| subPath.Contains("CRASH") && (subPath.Contains("PAD") || subPath.Contains("REPORT")); || subPath.Contains("CRASH") && (subPath.Contains("PAD") || subPath.Contains("REPORT"));
} }
internal static async Task<List<string>> 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, string subDirectory = null, bool filterCommon = false, Func<string, bool> validFunc = null) =>
{ await Task.Run(async () =>
List<string> executables = new();
if (Program.Canceled || !Directory.Exists(subDirectory ?? rootDirectory)) return null;
Thread.Sleep(0);
foreach (string path in Directory.GetFiles(subDirectory ?? rootDirectory, "*.exe"))
{ {
List<(string path, BinaryType binaryType)> executables = new();
if (Program.Canceled || !Directory.Exists(subDirectory ?? rootDirectory)) return null;
Thread.Sleep(0); Thread.Sleep(0);
if ((!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path)) && (validFunc is null || validFunc(path))) string[] files = Directory.GetFiles(subDirectory ?? rootDirectory, "*.exe");
executables.Add(path); foreach (string path in files)
}
string[] directories = Directory.GetDirectories(subDirectory ?? rootDirectory);
foreach (string directory in directories)
{
if (Program.Canceled) return null;
Thread.Sleep(0);
try
{ {
List<string> moreExecutables = await rootDirectory.GetExecutables(directory, filterCommon, validFunc); Thread.Sleep(0);
if (moreExecutables is not null) if (!executables.Any(e => e.path == path)
executables.AddRange(moreExecutables); && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
&& (validFunc is null || validFunc(path))
&& path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT64)
executables.Add((path, binaryType));
} }
catch { } foreach (string path in files)
} {
return !executables.Any() ? null : executables; Thread.Sleep(0);
}); if (!executables.Any(e => e.path == path)
&& (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
&& (validFunc is null || validFunc(path))
&& 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>> GetExecutableDirectories(this string rootDirectory, bool filterCommon = false, Func<string, bool> validFunc = null) => await Task.Run(async () => internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(this string rootDirectory, bool filterCommon = false, Func<string, bool> validFunc = null) =>
(await rootDirectory.GetExecutables(filterCommon: filterCommon, validFunc: validFunc) ?? await rootDirectory.GetExecutables()).Select(e => e = Path.GetDirectoryName(e)).Distinct().ToList()); await Task.Run(async () => (await rootDirectory.GetExecutables(filterCommon: filterCommon, validFunc: validFunc) ?? await rootDirectory.GetExecutables()).Select(e =>
{
e.path = Path.GetDirectoryName(e.path);
return e;
}).DistinctBy(e => e.path).ToList());
internal static void GetCreamApiComponents( internal static void GetCreamApiComponents(
this string directory, this string directory,

View file

@ -11,6 +11,8 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using static CreamInstaller.Resources.Resources;
namespace CreamInstaller.Steam; namespace CreamInstaller.Steam;
internal static class SteamLibrary internal static class SteamLibrary
@ -26,7 +28,7 @@ internal static class SteamLibrary
} }
} }
internal static async Task<List<string>> GetExecutableDirectories(string gameDirectory) => internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(string gameDirectory) =>
await Task.Run(async () => await gameDirectory.GetExecutableDirectories(filterCommon: true)); await Task.Run(async () => await gameDirectory.GetExecutableDirectories(filterCommon: true));
internal static async Task<List<(string appId, string name, string branch, int buildId, string gameDirectory)>> GetGames() => await Task.Run(async () => internal static async Task<List<(string appId, string name, string branch, int buildId, string gameDirectory)>> GetGames() => await Task.Run(async () =>

View file

@ -8,6 +8,8 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using static CreamInstaller.Resources.Resources;
namespace CreamInstaller.Ubisoft; namespace CreamInstaller.Ubisoft;
internal static class UbisoftLibrary internal static class UbisoftLibrary
@ -23,7 +25,7 @@ internal static class UbisoftLibrary
} }
} }
internal static async Task<List<string>> GetExecutableDirectories(string gameDirectory) => internal static async Task<List<(string directory, BinaryType binaryType)>> GetExecutableDirectories(string gameDirectory) =>
await Task.Run(async () => await gameDirectory.GetExecutableDirectories(filterCommon: true)); await Task.Run(async () => await gameDirectory.GetExecutableDirectories(filterCommon: true));
internal static async Task<List<(string gameId, string name, string gameDirectory)>> GetGames() => await Task.Run(() => internal static async Task<List<(string gameId, string name, string gameDirectory)>> GetGames() => await Task.Run(() =>

View file

@ -1,4 +1,6 @@
using Newtonsoft.Json; using CreamInstaller.Resources;
using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -132,14 +134,17 @@ internal static class ProgramData
internal static void UpdateKoaloaderProxyChoices() internal static void UpdateKoaloaderProxyChoices()
{ {
string defaultProxy = Resources.Resources.EmbeddedResources.Find(r => r.Contains("version_64")); string defaultProxy = "version";
List<(Platform platform, string id, string proxy)> choices = ReadKoaloaderProxyChoices() ?? new(); List<(Platform platform, string id, string proxy)> choices = ReadKoaloaderProxyChoices() ?? new();
foreach ((Platform platform, string id, string proxy) choice in choices.ToList()) foreach ((Platform platform, string id, string proxy) choice in choices.ToList())
if (ProgramSelection.FromPlatformId(choice.platform, choice.id) is ProgramSelection selection) if (ProgramSelection.FromPlatformId(choice.platform, choice.id) is ProgramSelection selection)
{ {
string proxy = choice.proxy;
if (proxy.Contains('.')) // convert pre-v4.1.0.0 choices
proxy.GetProxyInfoFromIdentifier(out proxy, out _);
if (selection.KoaloaderProxy is null) if (selection.KoaloaderProxy is null)
selection.KoaloaderProxy = choice.proxy; selection.KoaloaderProxy = proxy;
else if (selection.KoaloaderProxy != choice.proxy && choices.Remove(choice)) else if (selection.KoaloaderProxy != proxy && choices.Remove(choice))
choices.Add((selection.Platform, selection.Id, selection.KoaloaderProxy)); choices.Add((selection.Platform, selection.Id, selection.KoaloaderProxy));
} }
foreach (ProgramSelection selection in ProgramSelection.AllSafe) foreach (ProgramSelection selection in ProgramSelection.AllSafe)