- 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> <TargetFramework>net7.0-windows</TargetFramework>
<UseWindowsForms>True</UseWindowsForms> <UseWindowsForms>True</UseWindowsForms>
<ApplicationIcon>Resources\ini.ico</ApplicationIcon> <ApplicationIcon>Resources\ini.ico</ApplicationIcon>
<Version>4.9.4</Version> <Version>4.9.5</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

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

View file

@ -785,7 +785,11 @@ internal sealed partial class SelectForm : CustomForm
if (id == "PL") if (id == "PL")
{ {
_ = items.Add(new ToolStripSeparator()); _ = 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 ContextMenuItem("Repair", "Command Prompt", EventHandler));
} }
_ = items.Add(new ToolStripSeparator()); _ = items.Add(new ToolStripSeparator());
@ -890,11 +894,7 @@ internal sealed partial class SelectForm : CustomForm
private void OnAccept(bool uninstall = false) private void OnAccept(bool uninstall = false)
{ {
if (Selection.All.IsEmpty) if (Selection.All.IsEmpty || !uninstall && ParadoxLauncher.DlcDialog(this))
return;
if (Selection.AllEnabled.Any(selection => !Program.AreDllsLockedDialog(this, selection)))
return;
if (!uninstall && ParadoxLauncher.DlcDialog(this))
return; return;
Hide(); Hide();
InstallForm form = new(uninstall); InstallForm form = new(uninstall);

View file

@ -12,11 +12,7 @@ namespace CreamInstaller.Platforms.Paradox;
internal static class ParadoxLauncher internal static class ParadoxLauncher
{ {
public enum RepairResult public enum RepairResult { Failure = -1, Unnecessary = 0, Success }
{
ProgramRunning = -2, Failure, Unnecessary = 0,
Success
}
private static string installPath; private static string installPath;
@ -61,17 +57,14 @@ internal static class ParadoxLauncher
internal static async Task<RepairResult> Repair(Form form, Selection selection) internal static async Task<RepairResult> Repair(Form form, Selection selection)
{ {
InstallForm installForm = form as InstallForm; InstallForm installForm = form as InstallForm;
if (!Program.AreDllsLockedDialog(form, selection)) using DialogForm dialogForm = new(form);
return form is InstallForm
? throw new CustomMessageException("Repair failed! One or more DLLs crucial to unlocker installation are locked!")
: RepairResult.ProgramRunning;
bool smokeInstalled = false; bool smokeInstalled = false;
byte[] steamOriginalSdk32 = null; byte[] steamOriginalSdk32 = null;
byte[] steamOriginalSdk64 = null; byte[] steamOriginalSdk64 = null;
bool screamInstalled = false; bool screamInstalled = false;
byte[] epicOriginalSdk32 = null; byte[] epicOriginalSdk32 = null;
byte[] epicOriginalSdk64 = 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)) 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());
@ -97,11 +90,10 @@ internal static class ParadoxLauncher
if (epicOriginalSdk64 is null && api64.FileExists() && !api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64)) if (epicOriginalSdk64 is null && api64.FileExists() && !api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64))
epicOriginalSdk64 = api64.ReadFileBytes(true); 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) if (steamOriginalSdk32 is not null || steamOriginalSdk64 is not null || epicOriginalSdk32 is not null || epicOriginalSdk64 is not null)
{ {
bool neededRepair = false; 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 _); directory.GetSmokeApiComponents(out string api32, out _, out string api64, out _, out _, out _, out _, out _, out _);
if (steamOriginalSdk32 is not null && api32.IsResourceFile(ResourceIdentifier.Steamworks32)) if (steamOriginalSdk32 is not null && api32.IsResourceFile(ResourceIdentifier.Steamworks32))
@ -134,6 +126,8 @@ internal static class ParadoxLauncher
if (screamInstalled) if (screamInstalled)
await ScreamAPI.Install(directory, selection, generateConfig: false); await ScreamAPI.Install(directory, selection, generateConfig: false);
} }
if (!Program.Canceled)
{
if (neededRepair) if (neededRepair)
{ {
if (installForm is not null) if (installForm is not null)
@ -148,13 +142,20 @@ internal static class ParadoxLauncher
_ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", customFormText: "Paradox Launcher"); _ = dialogForm.Show(SystemIcons.Information, "Paradox Launcher does not need to be repaired.", customFormText: "Paradox Launcher");
return RepairResult.Unnecessary; 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 _ = form is InstallForm
? throw new CustomMessageException("Repair failed! " + "An original Steamworks and/or Epic Online Services file could not be found. " ? 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, : dialogForm.Show(SystemIcons.Error,
"Paradox Launcher repair failed!" + "\n\nAn original Steamworks and/or Epic Online Services file could not be found." "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.", + "\nYou will likely have to reinstall Paradox Launcher to fix this issue.", customFormText: "Paradox Launcher");
customFormText: "Paradox Launcher");
return RepairResult.Failure; return RepairResult.Failure;
} }
} }

View file

@ -129,7 +129,7 @@ internal static class SteamCMD
try try
{ {
byte[] file = await httpClient.GetByteArrayAsync(new Uri("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip")); 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.ExtractZip(DirectoryPath);
ArchivePath.DeleteFile(); ArchivePath.DeleteFile();
break; break;

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
@ -39,27 +38,7 @@ internal static class Program
internal static bool IsGameBlocked(string name, string directory = null) internal static bool IsGameBlocked(string name, string directory = null)
=> BlockProtectedGames && (ProtectedGames.Contains(name) || directory is not null && !ProtectedGameDirectoryExceptions.Contains(name) => BlockProtectedGames && (ProtectedGames.Contains(name) || directory is not null && !ProtectedGameDirectoryExceptions.Contains(name)
&& ProtectedGameDirectories.Any(path && ProtectedGameDirectories.Any(path => (directory + path).DirectoryExists()));
=> (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;
}
}
[STAThread] [STAThread]
private static void Main() private static void Main()

View file

@ -139,13 +139,13 @@ internal static class Koaloader
foreach (string proxyPath in directory.GetKoaloaderProxies().Where(proxyPath 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); 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)) 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); installForm?.UpdateUser($"Deleted {unlocker}: {Path.GetFileName(path)}", LogTextBox.Action, false);
} }
if (deleteConfig && old_config.FileExists()) if (deleteConfig && old_config.FileExists())
@ -174,7 +174,7 @@ internal static class Koaloader
string path = directory + @"\" + proxy + ".dll"; string path = directory + @"\" + proxy + ".dll";
foreach (string _path in directory.GetKoaloaderProxies().Where(p => p != path && p.FileExists() && p.IsResourceFile(ResourceIdentifier.Koaloader))) 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); installForm?.UpdateUser($"Deleted Koaloader: {Path.GetFileName(_path)}", LogTextBox.Action, false);
} }
if (path.FileExists() && !path.IsResourceFile(ResourceIdentifier.Koaloader)) 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) while (!Program.Canceled)
try try
{ {
using FileStream fileStream = new(filePath, FileMode.Create, FileAccess.Write); using FileStream fileStream = new(filePath, FileMode.Create, FileAccess.Write);
fileStream.Write(resource); fileStream.Write(resource);
break; return true;
} }
catch (Exception e) catch (Exception e)
{ {
if (filePath.IOWarn("Failed to write a crucial resource", e) is not DialogResult.OK) if (filePath.IOWarn("Failed to write a crucial resource", e) is not DialogResult.OK)
break; break;
} }
return false;
} }
internal static bool TryGetFileBinaryType(this string path, out BinaryType binaryType) => NativeImports.GetBinaryType(path, out binaryType); 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) if (Program.Canceled)
return null; return null;
if (executables.All(e => e.path != path) && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path)) if (executables.All(e => e.path != path) && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
&& (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType) && (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT64)
&& binaryType is BinaryType.BIT64)
executables.Add((path, binaryType)); executables.Add((path, binaryType));
} }
foreach (string path in rootDirectory.EnumerateDirectory("*.exe", true)) foreach (string path in rootDirectory.EnumerateDirectory("*.exe", true))
@ -513,8 +513,7 @@ internal static class Resources
if (Program.Canceled) if (Program.Canceled)
return null; return null;
if (executables.All(e => e.path != path) && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path)) if (executables.All(e => e.path != path) && (!filterCommon || !rootDirectory.IsCommonIncorrectExecutable(path))
&& (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType) && (validFunc is null || validFunc(path)) && path.TryGetFileBinaryType(out BinaryType binaryType) && binaryType is BinaryType.BIT32)
&& binaryType is BinaryType.BIT32)
executables.Add((path, binaryType)); executables.Add((path, binaryType));
} }
return executables.Count > 0 ? executables : null; return executables.Count > 0 ? executables : null;
@ -524,10 +523,9 @@ internal static class Resources
{ {
string subPath = path[rootDirectory.Length..].ToUpperInvariant(); string subPath = path[rootDirectory.Length..].ToUpperInvariant();
return subPath.Contains("SETUP") || subPath.Contains("REDIST") || subPath.Contains("SUPPORT") return 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("CEFPROCESS") || subPath.Contains("ZFGAMEBROWSER") || subPath.Contains("MONO") || subPath.Contains("PLUGINS") || subPath.Contains("ZFGAMEBROWSER") || subPath.Contains("MONO") || subPath.Contains("PLUGINS") || subPath.Contains("MODDING")
|| subPath.Contains("MODDING") || subPath.Contains("MOD") && subPath.Contains("MANAGER") || subPath.Contains("BATTLEYE") || subPath.Contains("MOD") && subPath.Contains("MANAGER") || subPath.Contains("BATTLEYE") || subPath.Contains("ANTICHEAT");
|| subPath.Contains("ANTICHEAT");
} }
internal static async Task<HashSet<string>> GetDllDirectoriesFromGameDirectory(this string gameDirectory, Platform platform) 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()) if (api32.FileExists())
{ {
api32.DeleteFile(); api32.DeleteFile(true);
installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false); installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api32)}", LogTextBox.Action, false);
} }
api32_o.MoveFile(api32!); api32_o.MoveFile(api32!);
@ -118,7 +118,7 @@ internal static class ScreamAPI
{ {
if (api64.FileExists()) if (api64.FileExists())
{ {
api64.DeleteFile(); api64.DeleteFile(true);
installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false); installForm?.UpdateUser($"Deleted ScreamAPI: {Path.GetFileName(api64)}", LogTextBox.Action, false);
} }
api64_o.MoveFile(api64!); 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 _); directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o, out _, out _);
if (api32.FileExists() && !api32_o.FileExists()) 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); installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api32)} -> {Path.GetFileName(api32_o)}", LogTextBox.Action, false);
} }
if (api32_o.FileExists()) if (api32_o.FileExists())
@ -154,7 +154,7 @@ internal static class ScreamAPI
} }
if (api64.FileExists() && !api64_o.FileExists()) 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); installForm?.UpdateUser($"Renamed EOS: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", LogTextBox.Action, false);
} }
if (api64_o.FileExists()) if (api64_o.FileExists())

View file

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

View file

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

View file

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

View file

@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using CreamInstaller.Forms; using CreamInstaller.Forms;
using CreamInstaller.Resources;
using CreamInstaller.Utility; using CreamInstaller.Utility;
using static CreamInstaller.Resources.Resources; 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 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); 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, 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'); string[] stackTrace = e.StackTrace?.Split('\n');
if (stackTrace is not null && stackTrace.Length > 0) 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) foreach (string line in stackTrace)
{ {
int atNum = line.IndexOf("at ", StringComparison.Ordinal); int atNum = line.IndexOf("at ", StringComparison.Ordinal);

View file

@ -12,21 +12,6 @@ namespace CreamInstaller.Utility;
internal static class SafeIO 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 bool DirectoryExists(this string directoryPath) => Directory.Exists(directoryPath);
internal static void CreateDirectory(this string directoryPath, bool crucial = false, Form form = null) internal static void CreateDirectory(this string directoryPath, bool crucial = false, Form form = null)
@ -37,7 +22,7 @@ internal static class SafeIO
try try
{ {
_ = Directory.CreateDirectory(directoryPath); _ = Directory.CreateDirectory(directoryPath);
break; return;
} }
catch (Exception e) catch (Exception e)
{ {
@ -54,7 +39,7 @@ internal static class SafeIO
try try
{ {
Directory.Move(directoryPath, newDirectoryPath); Directory.Move(directoryPath, newDirectoryPath);
break; return;
} }
catch (Exception e) catch (Exception e)
{ {
@ -71,7 +56,7 @@ internal static class SafeIO
try try
{ {
Directory.Delete(directoryPath, true); Directory.Delete(directoryPath, true);
break; return;
} }
catch (Exception e) catch (Exception e)
{ {
@ -148,7 +133,7 @@ internal static class SafeIO
try try
{ {
File.Move(filePath, newFilePath); File.Move(filePath, newFilePath);
break; return;
} }
catch (Exception e) catch (Exception e)
{ {
@ -165,7 +150,7 @@ internal static class SafeIO
try try
{ {
File.Delete(filePath); File.Delete(filePath);
break; return;
} }
catch (Exception e) catch (Exception e)
{ {
@ -214,7 +199,7 @@ internal static class SafeIO
try try
{ {
File.WriteAllText(filePath, text, Encoding.UTF8); File.WriteAllText(filePath, text, Encoding.UTF8);
break; return;
} }
catch (Exception e) catch (Exception e)
{ {
@ -231,7 +216,7 @@ internal static class SafeIO
try try
{ {
ZipFile.ExtractToDirectory(archivePath, destinationPath); ZipFile.ExtractToDirectory(archivePath, destinationPath);
break; return;
} }
catch (Exception e) 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) 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.ResolvePath() + "\n\n"; string description = message + ": " + (filePath.ResolvePath() ?? filePath) + "\n\n";
if (e is IOException && (e.HResult & 0x0000FFFF) == 225) // virus or potentially unwanted software 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 . . . "; description += "Please resolve your anti-virus and press retry to continue . . . ";
else break;
default:
description += e.FormatException(); description += e.FormatException();
return dialogForm.Show(SystemIcons.Warning, description, "Retry", "OK"); break;
}
DialogResult result = dialogForm.Show(SystemIcons.Warning, description, "Retry", "Cancel");
if (result is not DialogResult.OK)
Program.Canceled = true;
return result;
} }
} }