- Minor refactoring & optimization
- Removed the no-longer-necessary locked DLL check in favor of SafeIO
- Fixed uninstall all cancel functionality
- Improved SafeIO crucial checks and warning outputs
This commit is contained in:
pointfeev 2023-06-09 19:04:54 -04:00
parent 43b9d9f153
commit c5fc5f561a
18 changed files with 151 additions and 217 deletions

View file

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

View file

@ -14,14 +14,12 @@ namespace CreamInstaller.Forms;
internal sealed partial class InstallForm : CustomForm
{
private readonly HashSet<Selection> disabledSelections = new();
private readonly int programCount = Selection.AllEnabled.Count();
private readonly HashSet<Selection> activeSelections = new();
private readonly bool uninstalling;
private int completeOperationsCount;
private int operationsCount;
internal bool Reselecting;
private int selectionCount;
internal InstallForm(bool uninstall = false)
{
@ -77,7 +75,7 @@ internal sealed partial class InstallForm : CustomForm
foreach (string directory in invalidDirectories)
{
if (Program.Canceled)
throw new CustomMessageException("The operation was canceled.");
return;
directory.GetKoaloaderComponents(out string old_config, out string config);
if (directory.GetKoaloaderProxies().Any(proxy => proxy.FileExists() && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
|| directory != selection.RootDirectory && Koaloader.AutoLoadDLLs.Any(pair => (directory + @"\" + pair.dll).FileExists())
@ -91,7 +89,7 @@ internal sealed partial class InstallForm : CustomForm
foreach ((string directory, BinaryType _) in selection.ExecutableDirectories)
{
if (Program.Canceled)
throw new CustomMessageException("The operation was canceled.");
return;
directory.GetKoaloaderComponents(out string old_config, out string config);
if (directory.GetKoaloaderProxies().Any(proxy => proxy.FileExists() && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
|| Koaloader.AutoLoadDLLs.Any(pair => (directory + @"\" + pair.dll).FileExists()) || old_config.FileExists() || config.FileExists())
@ -105,15 +103,15 @@ internal sealed partial class InstallForm : CustomForm
foreach (string directory in selection.DllDirectories)
{
if (Program.Canceled)
throw new CustomMessageException("The operation was canceled.");
return;
if (selection.Platform is Platform.Steam or Platform.Paradox)
{
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string old_config,
out string config, out string old_log, out string log, out string cache);
if (uninstallProxy
? api32_o.FileExists() || api64_o.FileExists() || old_config.FileExists() || config.FileExists() || old_log.FileExists()
|| log.FileExists() || cache.FileExists()
: api32.FileExists() || api64.FileExists())
? api32_o.FileExists() || api64_o.FileExists() || old_config.FileExists() || config.FileExists() || old_log.FileExists() || log.FileExists()
|| cache.FileExists()
: api32.FileExists() || api64.FileExists())
{
UpdateUser(
$"{(uninstallProxy ? "Uninstalling" : "Installing")} SmokeAPI" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
@ -128,8 +126,8 @@ internal sealed partial class InstallForm : CustomForm
{
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out string log);
if (uninstallProxy
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists()
: api32.FileExists() || api64.FileExists())
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists()
: api32.FileExists() || api64.FileExists())
{
UpdateUser(
$"{(uninstallProxy ? "Uninstalling" : "Installing")} ScreamAPI" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
@ -144,8 +142,8 @@ internal sealed partial class InstallForm : CustomForm
{
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config, out string log);
if (uninstallProxy
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists()
: api32.FileExists() || api64.FileExists())
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists()
: api32.FileExists() || api64.FileExists())
{
UpdateUser(
$"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R1 Unlocker" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
@ -157,8 +155,8 @@ internal sealed partial class InstallForm : CustomForm
}
directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config, out log);
if (uninstallProxy
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists()
: old_api32.FileExists() || old_api64.FileExists() || api32.FileExists() || api64.FileExists())
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists()
: old_api32.FileExists() || old_api64.FileExists() || api32.FileExists() || api64.FileExists())
{
UpdateUser(
$"{(uninstallProxy ? "Uninstalling" : "Installing")} Uplay R2 Unlocker" + $" {(uninstallProxy ? "from" : "for")} " + selection.Name
@ -175,7 +173,7 @@ internal sealed partial class InstallForm : CustomForm
foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories)
{
if (Program.Canceled)
throw new CustomMessageException("The operation was canceled.");
return;
UpdateUser("Installing Koaloader to " + selection.Name + $" in directory \"{directory}\" . . . ", LogTextBox.Operation);
await Koaloader.Install(directory, binaryType, selection, selection.RootDirectory, this);
}
@ -184,19 +182,19 @@ internal sealed partial class InstallForm : CustomForm
private async Task Operate()
{
HashSet<Selection> programSelections = Selection.AllEnabled.ToHashSet();
operationsCount = programSelections.Count;
operationsCount = activeSelections.Count;
completeOperationsCount = 0;
foreach (Selection selection in programSelections)
foreach (Selection selection in activeSelections)
{
if (Program.Canceled || !Program.AreDllsLockedDialog(this, selection))
if (Program.Canceled)
throw new CustomMessageException("The operation was canceled.");
try
{
await OperateFor(selection);
if (Program.Canceled)
throw new CustomMessageException("The operation was canceled.");
UpdateUser($"Operation succeeded for {selection.Name}.", LogTextBox.Success);
selection.Enabled = false;
_ = disabledSelections.Add(selection);
_ = activeSelections.Remove(selection);
}
catch (Exception exception)
{
@ -205,15 +203,12 @@ internal sealed partial class InstallForm : CustomForm
++completeOperationsCount;
}
Program.Cleanup();
HashSet<Selection> failedSelections = Selection.AllEnabled.ToHashSet();
if (failedSelections.Count > 0)
if (failedSelections.Count == 1)
throw new CustomMessageException($"Operation failed for {failedSelections.First().Name}.");
int activeCount = activeSelections.Count;
if (activeCount > 0)
if (activeCount == 1)
throw new CustomMessageException($"Operation failed for {activeSelections.First().Name}.");
else
throw new CustomMessageException($"Operation failed for {failedSelections.Count} programs.");
foreach (Selection selection in disabledSelections)
selection.Enabled = true;
disabledSelections.Clear();
throw new CustomMessageException($"Operation failed for {activeCount} programs.");
}
private async void Start()
@ -227,7 +222,7 @@ internal sealed partial class InstallForm : CustomForm
try
{
await Operate();
UpdateUser($"DLC unlocker(s) successfully {(uninstalling ? "uninstalled" : "installed and generated")} for " + programCount + " program(s).",
UpdateUser($"DLC unlocker(s) successfully {(uninstalling ? "uninstalled" : "installed and generated")} for " + selectionCount + " program(s).",
LogTextBox.Success);
}
catch (Exception exception)
@ -241,13 +236,19 @@ internal sealed partial class InstallForm : CustomForm
reselectButton.Enabled = true;
}
private void OnLoad(object sender, EventArgs _)
private void OnLoad(object sender, EventArgs a)
{
retry:
try
{
userInfoLabel.Text = "Loading . . . ";
logTextBox.Text = string.Empty;
selectionCount = 0;
foreach (Selection selection in Selection.AllEnabled)
{
selectionCount++;
_ = activeSelections.Add(selection);
}
Start();
}
catch (Exception e)
@ -276,9 +277,6 @@ internal sealed partial class InstallForm : CustomForm
{
Program.Cleanup();
Reselecting = true;
foreach (Selection selection in disabledSelections)
selection.Enabled = true;
disabledSelections.Clear();
Close();
}
}

View file

@ -535,7 +535,7 @@ internal sealed partial class SelectForm : CustomForm
programsToScan is not null && programsToScan.Any(p => p.platform is Platform.Paradox && p.id == "PL")));
if (SteamLibrary.InstallPath.DirectoryExists())
foreach ((string appId, string name, string _, int _, string _) in (await SteamLibrary.GetGames()).Where(g
=> !Program.IsGameBlocked(g.name, g.gameDirectory)))
=> !Program.IsGameBlocked(g.name, g.gameDirectory)))
gameChoices.Add((Platform.Steam, appId, name,
programsToScan is not null && programsToScan.Any(p => p.platform is Platform.Steam && p.id == appId)));
if (EpicLibrary.EpicManifestsPath.DirectoryExists() || HeroicLibrary.HeroicLibraryPath.DirectoryExists())
@ -709,7 +709,7 @@ internal sealed partial class SelectForm : CustomForm
programsGroupBox.Size = programsGroupBox.Size with
{
Height = programsGroupBox.Size.Height - 3 - progressLabel.Size.Height - progressLabelGames.Size.Height - progressLabelDLCs.Size.Height
- progressBar.Size.Height
- progressBar.Size.Height
};
}
@ -723,7 +723,7 @@ internal sealed partial class SelectForm : CustomForm
programsGroupBox.Size = programsGroupBox.Size with
{
Height = programsGroupBox.Size.Height + 3 + progressLabel.Size.Height + progressLabelGames.Size.Height + progressLabelDLCs.Size.Height
+ progressBar.Size.Height
+ progressBar.Size.Height
};
}
@ -785,7 +785,11 @@ internal sealed partial class SelectForm : CustomForm
if (id == "PL")
{
_ = items.Add(new ToolStripSeparator());
async void EventHandler(object sender, EventArgs e) => await ParadoxLauncher.Repair(this, selection);
async void EventHandler(object sender, EventArgs e)
{
_ = await ParadoxLauncher.Repair(this, selection);
Program.Canceled = false;
}
_ = items.Add(new ContextMenuItem("Repair", "Command Prompt", EventHandler));
}
_ = items.Add(new ToolStripSeparator());
@ -890,11 +894,7 @@ internal sealed partial class SelectForm : CustomForm
private void OnAccept(bool uninstall = false)
{
if (Selection.All.IsEmpty)
return;
if (Selection.AllEnabled.Any(selection => !Program.AreDllsLockedDialog(this, selection)))
return;
if (!uninstall && ParadoxLauncher.DlcDialog(this))
if (Selection.All.IsEmpty || !uninstall && ParadoxLauncher.DlcDialog(this))
return;
Hide();
InstallForm form = new(uninstall);

View file

@ -155,7 +155,7 @@ internal sealed partial class UpdateForm : CustomForm
long bytesRead = 0;
int newBytes;
while (cancellation is not null && !Program.Canceled
&& (newBytes = await download.ReadAsync(buffer.AsMemory(0, buffer.Length), cancellation.Token)) != 0)
&& (newBytes = await download.ReadAsync(buffer.AsMemory(0, buffer.Length), cancellation.Token)) != 0)
{
if (cancellation is null || Program.Canceled)
throw new TaskCanceledException();

View file

@ -12,11 +12,7 @@ namespace CreamInstaller.Platforms.Paradox;
internal static class ParadoxLauncher
{
public enum RepairResult
{
ProgramRunning = -2, Failure, Unnecessary = 0,
Success
}
public enum RepairResult { Failure = -1, Unnecessary = 0, Success }
private static string installPath;
@ -61,26 +57,23 @@ internal static class ParadoxLauncher
internal static async Task<RepairResult> Repair(Form form, Selection selection)
{
InstallForm installForm = form as InstallForm;
if (!Program.AreDllsLockedDialog(form, selection))
return form is InstallForm
? throw new CustomMessageException("Repair failed! One or more DLLs crucial to unlocker installation are locked!")
: RepairResult.ProgramRunning;
using DialogForm dialogForm = new(form);
bool smokeInstalled = false;
byte[] steamOriginalSdk32 = null;
byte[] steamOriginalSdk64 = null;
bool screamInstalled = false;
byte[] epicOriginalSdk32 = null;
byte[] epicOriginalSdk64 = null;
foreach (string directory in selection.DllDirectories)
foreach (string directory in selection.DllDirectories.TakeWhile(_ => !Program.Canceled))
{
bool koaloaderInstalled = Koaloader.AutoLoadDLLs.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
.Any(pair => pair.path.FileExists() && pair.path.IsResourceFile());
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string old_config,
out string config, out _, out _, out _);
smokeInstalled = smokeInstalled || api32_o.FileExists() || api64_o.FileExists()
|| (old_config.FileExists() || config.FileExists()) && !koaloaderInstalled
|| api32.FileExists() && api32.IsResourceFile(ResourceIdentifier.Steamworks32)
|| api64.FileExists() && api64.IsResourceFile(ResourceIdentifier.Steamworks64);
|| (old_config.FileExists() || config.FileExists()) && !koaloaderInstalled
|| api32.FileExists() && api32.IsResourceFile(ResourceIdentifier.Steamworks32)
|| api64.FileExists() && api64.IsResourceFile(ResourceIdentifier.Steamworks64);
await SmokeAPI.Uninstall(directory, deleteOthers: false);
if (steamOriginalSdk32 is null && api32.FileExists() && !api32.IsResourceFile(ResourceIdentifier.Steamworks32))
steamOriginalSdk32 = api32.ReadFileBytes(true);
@ -88,20 +81,19 @@ internal static class ParadoxLauncher
steamOriginalSdk64 = api64.ReadFileBytes(true);
directory.GetScreamApiComponents(out api32, out api32_o, out api64, out api64_o, out config, out string log);
screamInstalled = screamInstalled || api32_o.FileExists() || api64_o.FileExists()
|| (config.FileExists() || log.FileExists()) && !koaloaderInstalled
|| api32.FileExists() && api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32)
|| api64.FileExists() && api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64);
|| (config.FileExists() || log.FileExists()) && !koaloaderInstalled
|| api32.FileExists() && api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32)
|| api64.FileExists() && api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64);
await ScreamAPI.Uninstall(directory, deleteOthers: false);
if (epicOriginalSdk32 is null && api32.FileExists() && !api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32))
epicOriginalSdk32 = api32.ReadFileBytes(true);
if (epicOriginalSdk64 is null && api64.FileExists() && !api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64))
epicOriginalSdk64 = api64.ReadFileBytes(true);
}
using DialogForm dialogForm = new(form);
if (steamOriginalSdk32 is not null || steamOriginalSdk64 is not null || epicOriginalSdk32 is not null || epicOriginalSdk64 is not null)
{
bool neededRepair = false;
foreach (string directory in selection.DllDirectories)
foreach (string directory in selection.DllDirectories.TakeWhile(_ => !Program.Canceled))
{
directory.GetSmokeApiComponents(out string api32, out _, out string api64, out _, out _, out _, out _, out _, out _);
if (steamOriginalSdk32 is not null && api32.IsResourceFile(ResourceIdentifier.Steamworks32))
@ -134,27 +126,36 @@ internal static class ParadoxLauncher
if (screamInstalled)
await ScreamAPI.Install(directory, selection, generateConfig: false);
}
if (neededRepair)
if (!Program.Canceled)
{
if (neededRepair)
{
if (installForm is not null)
installForm.UpdateUser("Paradox Launcher successfully repaired!", LogTextBox.Success);
else
_ = dialogForm.Show(form.Icon, "Paradox Launcher successfully repaired!", customFormText: "Paradox Launcher");
return RepairResult.Success;
}
if (installForm is not null)
installForm.UpdateUser("Paradox Launcher successfully repaired!", LogTextBox.Success);
installForm.UpdateUser("Paradox Launcher did not need to be repaired.", LogTextBox.Success);
else
_ = dialogForm.Show(form.Icon, "Paradox Launcher successfully repaired!", customFormText: "Paradox Launcher");
return RepairResult.Success;
_ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", customFormText: "Paradox Launcher");
return RepairResult.Unnecessary;
}
if (installForm is not null)
installForm.UpdateUser("Paradox Launcher did not need to be repaired.", LogTextBox.Success);
else
_ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", customFormText: "Paradox Launcher");
return RepairResult.Unnecessary;
}
if (Program.Canceled)
{
_ = form is InstallForm
? throw new CustomMessageException("Repair failed! The operation was canceled.")
: dialogForm.Show(SystemIcons.Error, "Paradox Launcher repair failed! The operation was canceled.", customFormText: "Paradox Launcher");
return RepairResult.Failure;
}
_ = form is InstallForm
? throw new CustomMessageException("Repair failed! " + "An original Steamworks and/or Epic Online Services file could not be found. "
+ "You will likely have to reinstall Paradox Launcher to fix this issue.")
+ "You will likely have to reinstall Paradox Launcher to fix this issue.")
: dialogForm.Show(SystemIcons.Error,
"Paradox Launcher repair failed!" + "\n\nAn original Steamworks and/or Epic Online Services file could not be found."
+ "\nYou will likely have to reinstall Paradox Launcher to fix this issue.",
customFormText: "Paradox Launcher");
+ "\nYou will likely have to reinstall Paradox Launcher to fix this issue.", customFormText: "Paradox Launcher");
return RepairResult.Failure;
}
}

View file

@ -42,7 +42,7 @@ internal static class SteamCMD
private static string GetArguments(string appId)
=> AttemptCount.TryGetValue(appId, out int attempts)
? $@"@ShutdownOnFailedCommand 0 +force_install_dir {DirectoryPath} +login anonymous +app_info_print {appId} "
+ string.Concat(Enumerable.Repeat("+app_update 4 ", attempts)) + "+quit"
+ string.Concat(Enumerable.Repeat("+app_update 4 ", attempts)) + "+quit"
: $"+login anonymous +app_info_print {appId} +quit";
private static async Task<string> Run(string appId)
@ -129,7 +129,7 @@ internal static class SteamCMD
try
{
byte[] file = await httpClient.GetByteArrayAsync(new Uri("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip"));
file.WriteResource(ArchivePath);
_ = file.WriteResource(ArchivePath);
ArchivePath.ExtractZip(DirectoryPath);
ArchivePath.DeleteFile();
break;

View file

@ -31,7 +31,7 @@ internal static class SteamLibrary
if (Program.Canceled)
return games;
foreach ((string appId, string name, string branch, int buildId, string gameDirectory) game in (await GetGamesFromLibraryDirectory(
libraryDirectory)).Where(game => games.All(_game => _game.appId != game.appId)))
libraryDirectory)).Where(game => games.All(_game => _game.appId != game.appId)))
games.Add(game);
}
return games;

View file

@ -71,7 +71,7 @@ internal static class SteamStore
(Exception e)
{
DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "")
+ ": Unsuccessful serialization (" + e.Message + ")");
+ ": Unsuccessful serialization (" + e.Message + ")");
}
#else
{
@ -82,13 +82,13 @@ internal static class SteamStore
}
#if DEBUG
DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "")
+ ": Response data null (" + app.Value.ToString(Formatting.None) + ")");
+ ": Response data null (" + app.Value.ToString(Formatting.None) + ")");
#endif
}
#if DEBUG
else
DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "")
+ ": Response details null (" + app.Value.ToString(Formatting.None) + ")");
+ ": Response details null (" + app.Value.ToString(Formatting.None) + ")");
#endif
}
catch
@ -96,7 +96,7 @@ internal static class SteamStore
(Exception e)
{
DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "")
+ ": Unsuccessful deserialization (" + e.Message + ")");
+ ": Unsuccessful deserialization (" + e.Message + ")");
}
#else
{
@ -106,7 +106,7 @@ internal static class SteamStore
#if DEBUG
else
DebugForm.Current.Log("Steam store query failed on attempt #" + attempts + " for " + appId + (isDlc ? " (DLC)" : "")
+ ": Response deserialization null");
+ ": Response deserialization null");
#endif
}
else

View file

@ -1,6 +1,5 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
@ -39,27 +38,7 @@ internal static class Program
internal static bool IsGameBlocked(string name, string directory = null)
=> BlockProtectedGames && (ProtectedGames.Contains(name) || directory is not null && !ProtectedGameDirectoryExceptions.Contains(name)
&& ProtectedGameDirectories.Any(path
=> (directory + path).DirectoryExists()));
internal static bool AreDllsLockedDialog(Form form, Selection selection)
{
while (true)
{
if (selection.AreDllsLocked)
{
using DialogForm dialogForm = new(form);
if (dialogForm.Show(SystemIcons.Error,
$"ERROR: One or more DLLs crucial to unlocker installation are locked for {selection.Name}!"
+ "\n\nPlease close the program/game or resolve your anti-virus and press retry to continue . . . ", "Retry", "Cancel")
== DialogResult.OK)
continue;
}
else
return true;
return false;
}
}
&& ProtectedGameDirectories.Any(path => (directory + path).DirectoryExists()));
[STAThread]
private static void Main()

View file

@ -24,11 +24,11 @@ internal static class Koaloader
internal static IEnumerable<string> GetKoaloaderProxies(this string directory)
=> from resource in EmbeddedResources
select resource[(resource.IndexOf('.') + 1)..]
into resource
select resource[(resource.IndexOf('.') + 1)..]
into resource
select directory + @"\" + resource;
select resource[(resource.IndexOf('.') + 1)..]
into resource
select resource[(resource.IndexOf('.') + 1)..]
into resource
select directory + @"\" + resource;
internal static void GetKoaloaderComponents(this string directory, out string old_config, out string config)
{
@ -137,15 +137,15 @@ internal static class Koaloader
{
directory.GetKoaloaderComponents(out string old_config, out string config);
foreach (string proxyPath in directory.GetKoaloaderProxies().Where(proxyPath
=> proxyPath.FileExists() && proxyPath.IsResourceFile(ResourceIdentifier.Koaloader)))
=> proxyPath.FileExists() && proxyPath.IsResourceFile(ResourceIdentifier.Koaloader)))
{
proxyPath.DeleteFile();
proxyPath.DeleteFile(true);
installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(proxyPath)}", LogTextBox.Action, false);
}
foreach ((string unlocker, string path) in AutoLoadDLLs.Select(pair => (pair.unlocker, path: directory + @"\" + pair.dll))
.Where(pair => pair.path.FileExists() && pair.path.IsResourceFile()))
.Where(pair => pair.path.FileExists() && pair.path.IsResourceFile()))
{
path.DeleteFile();
path.DeleteFile(true);
installForm?.UpdateUser($"Deleted {unlocker}: {Path.GetFileName(path)}", LogTextBox.Action, false);
}
if (deleteConfig && old_config.FileExists())
@ -174,7 +174,7 @@ internal static class Koaloader
string path = directory + @"\" + proxy + ".dll";
foreach (string _path in directory.GetKoaloaderProxies().Where(p => p != path && p.FileExists() && p.IsResourceFile(ResourceIdentifier.Koaloader)))
{
_path.DeleteFile();
_path.DeleteFile(true);
installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(_path)}", LogTextBox.Action, false);
}
if (path.FileExists() && !path.IsResourceFile(ResourceIdentifier.Koaloader))

View file

@ -464,20 +464,21 @@ internal static class Resources
}
}
internal static void WriteResource(this byte[] resource, string filePath)
internal static bool WriteResource(this byte[] resource, string filePath)
{
while (!Program.Canceled)
try
{
using FileStream fileStream = new(filePath, FileMode.Create, FileAccess.Write);
fileStream.Write(resource);
break;
return true;
}
catch (Exception e)
{
if (filePath.IOWarn("Failed to write a crucial resource", e) is not DialogResult.OK)
break;
}
return false;
}
internal static bool TryGetFileBinaryType(this string path, out BinaryType binaryType) => NativeImports.GetBinaryType(path, out binaryType);
@ -504,8 +505,7 @@ internal static class Resources
if (Program.Canceled)
return null;
if (executables.All(e => e.path != path) && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
&& (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType)
&& binaryType is BinaryType.BIT64)
&& (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT64)
executables.Add((path, binaryType));
}
foreach (string path in rootDirectory.EnumerateDirectory("*.exe", true))
@ -513,8 +513,7 @@ internal static class Resources
if (Program.Canceled)
return null;
if (executables.All(e => e.path != path) && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
&& (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType)
&& binaryType is BinaryType.BIT32)
&& (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT32)
executables.Add((path, binaryType));
}
return executables.Count > 0 ? executables : null;
@ -524,10 +523,9 @@ internal static class Resources
{
string subPath = path[rootDirectory.Length..].ToUpperInvariant();
return subPath.Contains("SETUP") || subPath.Contains("REDIST") || subPath.Contains("SUPPORT")
|| 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("MODDING") || subPath.Contains("MOD") && subPath.Contains("MANAGER") || subPath.Contains("BATTLEYE")
|| subPath.Contains("ANTICHEAT");
|| 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("MODDING")
|| subPath.Contains("MOD") && subPath.Contains("MANAGER") || subPath.Contains("BATTLEYE") || subPath.Contains("ANTICHEAT");
}
internal static async Task<HashSet<string>> GetDllDirectoriesFromGameDirectory(this string gameDirectory, Platform platform)

View file

@ -108,7 +108,7 @@ internal static class ScreamAPI
{
if (api32.FileExists())
{
api32.DeleteFile();
api32.DeleteFile(true);
installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false);
}
api32_o.MoveFile(api32!);
@ -118,7 +118,7 @@ internal static class ScreamAPI
{
if (api64.FileExists())
{
api64.DeleteFile();
api64.DeleteFile(true);
installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false);
}
api64_o.MoveFile(api64!);
@ -144,7 +144,7 @@ internal static class ScreamAPI
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out _, out _);
if (api32.FileExists() && !api32_o.FileExists())
{
api32.MoveFile(api32_o!);
api32.MoveFile(api32_o!, true);
installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
}
if (api32_o.FileExists())
@ -154,7 +154,7 @@ internal static class ScreamAPI
}
if (api64.FileExists() && !api64_o.FileExists())
{
api64.MoveFile(api64_o!);
api64.MoveFile(api64_o!, true);
installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
}
if (api64_o.FileExists())

View file

@ -157,7 +157,7 @@ internal static class SmokeAPI
{
if (api32.FileExists())
{
api32.DeleteFile();
api32.DeleteFile(true);
installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false);
}
api32_o.MoveFile(api32!);
@ -167,7 +167,7 @@ internal static class SmokeAPI
{
if (api64.FileExists())
{
api64.DeleteFile();
api64.DeleteFile(true);
installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false);
}
api64_o.MoveFile(api64!);
@ -214,7 +214,7 @@ internal static class SmokeAPI
directory.GetSmokeApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out _, out _, out _, out _, out _);
if (api32.FileExists() && !api32_o.FileExists())
{
api32.MoveFile(api32_o!);
api32.MoveFile(api32_o!, true);
installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
}
if (api32_o.FileExists())
@ -224,7 +224,7 @@ internal static class SmokeAPI
}
if (api64.FileExists() && !api64_o.FileExists())
{
api64.MoveFile(api64_o!);
api64.MoveFile(api64_o!, true);
installForm?.UpdateUser($"Renamed Steamworks: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
}
if (api64_o.FileExists())

View file

@ -77,7 +77,7 @@ internal static class UplayR1
{
if (api32.FileExists())
{
api32.DeleteFile();
api32.DeleteFile(true);
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api32)}", LogTextBox.Action, false);
}
api32_o.MoveFile(api32!);
@ -87,7 +87,7 @@ internal static class UplayR1
{
if (api64.FileExists())
{
api64.DeleteFile();
api64.DeleteFile(true);
installForm?.UpdateUser($"Deleted Uplay R1 Unlocker: {Path.GetFileName(api64)}", LogTextBox.Action, false);
}
api64_o.MoveFile(api64!);
@ -112,7 +112,7 @@ internal static class UplayR1
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out _, out _);
if (api32.FileExists() && !api32_o.FileExists())
{
api32.MoveFile(api32_o!);
api32.MoveFile(api32_o!, true);
installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
}
if (api32_o.FileExists())
@ -122,7 +122,7 @@ internal static class UplayR1
}
if (api64.FileExists() && !api64_o.FileExists())
{
api64.MoveFile(api64_o!);
api64.MoveFile(api64_o!, true);
installForm?.UpdateUser($"Renamed Uplay R1: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
}
if (api64_o.FileExists())

View file

@ -83,7 +83,7 @@ internal static class UplayR2
string api = old_api32.FileExists() ? old_api32 : api32;
if (api.FileExists())
{
api.DeleteFile();
api.DeleteFile(true);
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false);
}
api32_o.MoveFile(api!);
@ -94,7 +94,7 @@ internal static class UplayR2
string api = old_api64.FileExists() ? old_api64 : api64;
if (api.FileExists())
{
api.DeleteFile();
api.DeleteFile(true);
installForm?.UpdateUser($"Deleted Uplay R2 Unlocker: {Path.GetFileName(api)}", LogTextBox.Action, false);
}
api64_o.MoveFile(api!);
@ -121,7 +121,7 @@ internal static class UplayR2
string api = old_api32.FileExists() ? old_api32 : api32;
if (api.FileExists() && !api32_o.FileExists())
{
api.MoveFile(api32_o!);
api.MoveFile(api32_o!, true);
installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
}
if (api32_o.FileExists())
@ -132,7 +132,7 @@ internal static class UplayR2
api = old_api64.FileExists() ? old_api64 : api64;
if (api.FileExists() && !api64_o.FileExists())
{
api.MoveFile(api64_o!);
api.MoveFile(api64_o!, true);
installForm?.UpdateUser($"Renamed Uplay R2: {Path.GetFileName(api)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
}
if (api64_o.FileExists())

View file

@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using CreamInstaller.Forms;
using CreamInstaller.Resources;
using CreamInstaller.Utility;
using static CreamInstaller.Resources.Resources;
@ -62,47 +61,6 @@ internal sealed class Selection : IEquatable<Selection>
internal IEnumerable<SelectionDLC> DLC => SelectionDLC.All.Keys.Where(dlc => dlc.Selection.Equals(this));
internal bool AreDllsLocked
{
get
{
foreach (string directory in DllDirectories)
{
if (Platform is Platform.Steam or Platform.Paradox)
{
directory.GetCreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config);
if (api32.FileLocked() || api32_o.FileLocked() || api64.FileLocked() || api64_o.FileLocked() || config.FileLocked())
return true;
directory.GetSmokeApiComponents(out api32, out api32_o, out api64, out api64_o, out string old_config, out config, out string old_log,
out string log, out string cache);
if (api32.FileLocked() || api32_o.FileLocked() || api64.FileLocked() || api64_o.FileLocked() || old_config.FileLocked()
|| config.FileLocked() || old_log.FileLocked() || log.FileLocked() || cache.FileLocked())
return true;
}
if (Platform is Platform.Epic or Platform.Paradox)
{
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out string config,
out string log);
if (api32.FileLocked() || api32_o.FileLocked() || api64.FileLocked() || api64_o.FileLocked() || config.FileLocked() || log.FileLocked())
return true;
}
if (Platform is Platform.Ubisoft)
{
directory.GetUplayR1Components(out string api32, out string api32_o, out string api64, out string api64_o, out string config,
out string log);
if (api32.FileLocked() || api32_o.FileLocked() || api64.FileLocked() || api64_o.FileLocked() || config.FileLocked() || log.FileLocked())
return true;
directory.GetUplayR2Components(out string old_api32, out string old_api64, out api32, out api32_o, out api64, out api64_o, out config,
out log);
if (old_api32.FileLocked() || old_api64.FileLocked() || api32.FileLocked() || api32_o.FileLocked() || api64.FileLocked()
|| api64_o.FileLocked() || config.FileLocked() || log.FileLocked())
return true;
}
}
return false;
}
}
public bool Equals(Selection other) => other is not null && (ReferenceEquals(this, other) || Id == other.Id && Platform == other.Platform);
internal static Selection GetOrCreate(Platform platform, string id, string name, string rootDirectory, HashSet<string> dllDirectories,

View file

@ -21,7 +21,7 @@ internal static class ExceptionHandler
string[] stackTrace = e.StackTrace?.Split('\n');
if (stackTrace is not null && stackTrace.Length > 0)
{
_ = output.Append(e.GetType() + (": " + e.Message));
_ = output.Append($"[{e.HResult & 0x0000FFFF}] {e.GetType()}: {e.Message}");
foreach (string line in stackTrace)
{
int atNum = line.IndexOf("at ", StringComparison.Ordinal);

View file

@ -12,21 +12,6 @@ namespace CreamInstaller.Utility;
internal static class SafeIO
{
internal static bool FileLocked(this string filePath)
{
if (!FileExists(filePath))
return false;
try
{
File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None).Close();
}
catch
{
return true;
}
return false;
}
internal static bool DirectoryExists(this string directoryPath) => Directory.Exists(directoryPath);
internal static void CreateDirectory(this string directoryPath, bool crucial = false, Form form = null)
@ -37,7 +22,7 @@ internal static class SafeIO
try
{
_ = Directory.CreateDirectory(directoryPath);
break;
return;
}
catch (Exception e)
{
@ -54,7 +39,7 @@ internal static class SafeIO
try
{
Directory.Move(directoryPath, newDirectoryPath);
break;
return;
}
catch (Exception e)
{
@ -71,12 +56,12 @@ internal static class SafeIO
try
{
Directory.Delete(directoryPath, true);
break;
return;
}
catch (Exception e)
{
if (!crucial || !directoryPath.DirectoryExists()
|| directoryPath.IOWarn("Failed to delete a crucial directory", e, form) is not DialogResult.OK)
|| directoryPath.IOWarn("Failed to delete a crucial directory", e, form) is not DialogResult.OK)
break;
}
}
@ -96,7 +81,7 @@ internal static class SafeIO
catch (Exception e)
{
if (!crucial || !directoryPath.DirectoryExists()
|| directoryPath.IOWarn("Failed to enumerate a crucial directory's files", e, form) is not DialogResult.OK)
|| directoryPath.IOWarn("Failed to enumerate a crucial directory's files", e, form) is not DialogResult.OK)
break;
}
return Enumerable.Empty<string>();
@ -117,7 +102,7 @@ internal static class SafeIO
catch (Exception e)
{
if (!crucial || !directoryPath.DirectoryExists()
|| directoryPath.IOWarn("Failed to enumerate a crucial directory's subdirectories", e, form) is not DialogResult.OK)
|| directoryPath.IOWarn("Failed to enumerate a crucial directory's subdirectories", e, form) is not DialogResult.OK)
break;
}
return Enumerable.Empty<string>();
@ -148,7 +133,7 @@ internal static class SafeIO
try
{
File.Move(filePath, newFilePath);
break;
return;
}
catch (Exception e)
{
@ -165,7 +150,7 @@ internal static class SafeIO
try
{
File.Delete(filePath);
break;
return;
}
catch (Exception e)
{
@ -214,7 +199,7 @@ internal static class SafeIO
try
{
File.WriteAllText(filePath, text, Encoding.UTF8);
break;
return;
}
catch (Exception e)
{
@ -231,7 +216,7 @@ internal static class SafeIO
try
{
ZipFile.ExtractToDirectory(archivePath, destinationPath);
break;
return;
}
catch (Exception e)
{
@ -251,11 +236,26 @@ internal static class SafeIO
private static DialogResult IOWarnInternal(this string filePath, string message, Exception e, Form form = null)
{
using DialogForm dialogForm = new(form);
string description = message + ": " + filePath.ResolvePath() + "\n\n";
if (e is IOException && (e.HResult & 0x0000FFFF) == 225) // virus or potentially unwanted software
description += "Please resolve your anti-virus and press retry to continue . . . ";
else
description += e.FormatException();
return dialogForm.Show(SystemIcons.Warning, description, "Retry", "OK");
string description = message + ": " + (filePath.ResolvePath() ?? filePath) + "\n\n";
int code = e.HResult & 0x0000FFFF;
switch (code) // https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes
{
case 5: // ERROR_ACCESS_DENIED
case 32: // ERROR_SHARING_VIOLATION
case 33: // ERROR_LOCK_VIOLATION
description += "Please close the program/game and press retry to continue . . . ";
break;
case 225: // ERROR_VIRUS_INFECTED
case 226: // ERROR_VIRUS_DELETED
description += "Please resolve your anti-virus and press retry to continue . . . ";
break;
default:
description += e.FormatException();
break;
}
DialogResult result = dialogForm.Show(SystemIcons.Warning, description, "Retry", "Cancel");
if (result is not DialogResult.OK)
Program.Canceled = true;
return result;
}
}