From b3526c7fbf01d9f585f3ee4f1ec1c15cb28b8af8 Mon Sep 17 00:00:00 2001 From: pointfeev Date: Fri, 21 Jan 2022 16:10:15 -0500 Subject: [PATCH] v2.2.1.0 - Converted multiple methods to asynchronous to improve performance - Added a minimal delay to the install form updates to keep the log from glitching - Added double buffering to all controls to reduce flickering - Fixed the cancel button not fully cancelling SteamCMD processes - Internalized all possible classes, methods, accessors and fields --- CreamInstaller/Classes/ExceptionHandler.cs | 8 +- CreamInstaller/Classes/InstallationLog.cs | 18 ++-- CreamInstaller/Classes/ProgramSelection.cs | 44 ++++---- CreamInstaller/Classes/SteamCMD.cs | 66 +++++++----- CreamInstaller/CreamInstaller.csproj | 2 +- CreamInstaller/Forms/Components/CustomForm.cs | 27 +++++ .../Forms/Components/CustomTreeView.cs | 4 +- CreamInstaller/Forms/DialogForm.cs | 8 +- CreamInstaller/Forms/InstallForm.cs | 100 ++++++++---------- CreamInstaller/Forms/MainForm.cs | 5 +- CreamInstaller/Forms/SelectForm.Designer.cs | 18 ++-- CreamInstaller/Forms/SelectForm.cs | 46 ++++---- CreamInstaller/Program.cs | 41 +++---- .../Resources/FileResourceExtensions.cs | 4 +- 14 files changed, 210 insertions(+), 181 deletions(-) create mode 100644 CreamInstaller/Forms/Components/CustomForm.cs diff --git a/CreamInstaller/Classes/ExceptionHandler.cs b/CreamInstaller/Classes/ExceptionHandler.cs index ef8420f..f027b47 100644 --- a/CreamInstaller/Classes/ExceptionHandler.cs +++ b/CreamInstaller/Classes/ExceptionHandler.cs @@ -3,9 +3,9 @@ using System.Windows.Forms; namespace CreamInstaller { - public static class ExceptionHandler + internal static class ExceptionHandler { - public static bool OutputException(Exception e) + internal static bool OutputException(Exception e) { while (e.InnerException is not null) { @@ -48,7 +48,7 @@ namespace CreamInstaller } } - public class CustomMessageException : Exception + internal class CustomMessageException : Exception { private readonly string message; public override string Message => message ?? "CustomMessageException"; @@ -58,7 +58,7 @@ namespace CreamInstaller return Message; } - public CustomMessageException(string message) + internal CustomMessageException(string message) { this.message = message; } diff --git a/CreamInstaller/Classes/InstallationLog.cs b/CreamInstaller/Classes/InstallationLog.cs index d0eeea9..65be8bd 100644 --- a/CreamInstaller/Classes/InstallationLog.cs +++ b/CreamInstaller/Classes/InstallationLog.cs @@ -3,17 +3,17 @@ using System.Windows.Forms; namespace CreamInstaller { - public static class InstallationLog + internal static class InstallationLog { - public static readonly Color Background = Color.DarkSlateGray; - public static readonly Color Operation = Color.LightGray; - public static readonly Color Resource = Color.LightBlue; - public static readonly Color Success = Color.LightGreen; - public static readonly Color Cleanup = Color.YellowGreen; - public static readonly Color Warning = Color.Yellow; - public static readonly Color Error = Color.DarkOrange; + internal static readonly Color Background = Color.DarkSlateGray; + internal static readonly Color Operation = Color.LightGray; + internal static readonly Color Resource = Color.LightBlue; + internal static readonly Color Success = Color.LightGreen; + internal static readonly Color Cleanup = Color.YellowGreen; + internal static readonly Color Warning = Color.Yellow; + internal static readonly Color Error = Color.DarkOrange; - public static void AppendText(this RichTextBox logTextBox, string text, Color color) + internal static void AppendText(this RichTextBox logTextBox, string text, Color color) { logTextBox.SelectionStart = logTextBox.TextLength; logTextBox.SelectionLength = 0; diff --git a/CreamInstaller/Classes/ProgramSelection.cs b/CreamInstaller/Classes/ProgramSelection.cs index e8d884b..9e20516 100644 --- a/CreamInstaller/Classes/ProgramSelection.cs +++ b/CreamInstaller/Classes/ProgramSelection.cs @@ -6,23 +6,23 @@ using System.Linq; namespace CreamInstaller { - public class ProgramSelection + internal class ProgramSelection { - public bool Enabled = false; - public bool Usable = true; + internal bool Enabled = false; + internal bool Usable = true; - public string Name; - public string RootDirectory; - public int SteamAppId; - public List SteamApiDllDirectories; + internal string Name; + internal string RootDirectory; + internal int SteamAppId; + internal List SteamApiDllDirectories; - public VProperty AppInfo = null; + internal VProperty AppInfo = null; - public readonly SortedList AllSteamDlc = new(); - public readonly SortedList SelectedSteamDlc = new(); - public readonly List>> ExtraSteamAppIdDlc = new(); + internal readonly SortedList AllSteamDlc = new(); + internal readonly SortedList SelectedSteamDlc = new(); + internal readonly List>> ExtraSteamAppIdDlc = new(); - public bool AreSteamApiDllsLocked + internal bool AreSteamApiDllsLocked { get { @@ -51,7 +51,7 @@ namespace CreamInstaller } } - public void ToggleDlc(int dlcAppId, bool enabled) + internal void ToggleDlc(int dlcAppId, bool enabled) { foreach (KeyValuePair dlcApp in AllSteamDlc) { @@ -64,7 +64,7 @@ namespace CreamInstaller Enabled = SelectedSteamDlc.Any(); } - public void ToggleAllDlc(bool enabled) + internal void ToggleAllDlc(bool enabled) { if (!enabled) { @@ -81,12 +81,12 @@ namespace CreamInstaller Enabled = SelectedSteamDlc.Any(); } - public ProgramSelection() + internal ProgramSelection() { All.Add(this); } - public void Validate() + internal void Validate() { SteamApiDllDirectories.RemoveAll(directory => !Directory.Exists(directory)); if (!Directory.Exists(RootDirectory) || !SteamApiDllDirectories.Any()) @@ -95,23 +95,23 @@ namespace CreamInstaller } } - public static void ValidateAll() + internal static void ValidateAll() { All.ForEach(selection => selection.Validate()); } - public static List All => Program.ProgramSelections; + internal static List All => Program.ProgramSelections; - public static List AllSafe => All.FindAll(s => s.Usable); + internal static List AllSafe => All.FindAll(s => s.Usable); - public static List AllSafeEnabled => AllSafe.FindAll(s => s.Enabled); + internal static List AllSafeEnabled => AllSafe.FindAll(s => s.Enabled); - public static ProgramSelection FromAppId(int appId) + internal static ProgramSelection FromAppId(int appId) { return AllSafe.Find(s => s.SteamAppId == appId); } - public static KeyValuePair? GetDlcFromAppId(int appId) + internal static KeyValuePair? GetDlcFromAppId(int appId) { foreach (ProgramSelection selection in AllSafe) { diff --git a/CreamInstaller/Classes/SteamCMD.cs b/CreamInstaller/Classes/SteamCMD.cs index fd36bca..bc3c22d 100644 --- a/CreamInstaller/Classes/SteamCMD.cs +++ b/CreamInstaller/Classes/SteamCMD.cs @@ -8,26 +8,30 @@ using System.IO.Compression; using System.Linq; using System.Net.Http; using System.Text; +using System.Threading.Tasks; using System.Windows.Forms; namespace CreamInstaller { - public static class SteamCMD + internal static class SteamCMD { - public static readonly string DirectoryPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\CreamInstaller"; - public static readonly string FilePath = DirectoryPath + @"\steamcmd.exe"; - public static readonly string ArchivePath = DirectoryPath + @"\steamcmd.zip"; - public static readonly string DllPath = DirectoryPath + @"\steamclient.dll"; - public static readonly string AppCachePath = DirectoryPath + @"\appcache"; - public static readonly string AppCacheAppInfoPath = AppCachePath + @"\appinfo.vdf"; - public static readonly string AppInfoPath = DirectoryPath + @"\appinfo"; + internal static readonly string DirectoryPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\CreamInstaller"; + internal static readonly string FilePath = DirectoryPath + @"\steamcmd.exe"; + internal static readonly string ArchivePath = DirectoryPath + @"\steamcmd.zip"; + internal static readonly string DllPath = DirectoryPath + @"\steamclient.dll"; + internal static readonly string AppCachePath = DirectoryPath + @"\appcache"; + internal static readonly string AppCacheAppInfoPath = AppCachePath + @"\appinfo.vdf"; + internal static readonly string AppInfoPath = DirectoryPath + @"\appinfo"; - public static readonly Version MinimumAppInfoVersion = Version.Parse("2.0.3.2"); - public static readonly string AppInfoVersionPath = AppInfoPath + @"\version.txt"; + internal static readonly Version MinimumAppInfoVersion = Version.Parse("2.0.3.2"); + internal static readonly string AppInfoVersionPath = AppInfoPath + @"\version.txt"; - public static bool Run(string command, out string output) + internal static string Run(string command) { - bool success = true; + if (Program.Canceled) + { + return ""; + } List logs = new(); ProcessStartInfo processStartInfo = new() { @@ -50,18 +54,17 @@ namespace CreamInstaller process.BeginErrorReadLine(); process.WaitForExit(); } - output = string.Join("\r\n", logs); - return success; + return string.Join("\r\n", logs); } - public static void Setup() + internal static async Task Setup() { - Kill(); + await Kill(); if (!File.Exists(FilePath)) { using (HttpClient httpClient = new()) { - byte[] file = httpClient.GetByteArrayAsync("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip").Result; + byte[] file = await httpClient.GetByteArrayAsync("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip"); file.Write(ArchivePath); } @@ -85,11 +88,11 @@ namespace CreamInstaller } if (!File.Exists(DllPath)) { - Run($@"+quit", out _); + Run($@"+quit"); } } - public static bool GetAppInfo(int appId, out VProperty appInfo, string branch = "public", int buildId = 0) + internal static bool GetAppInfo(int appId, out VProperty appInfo, string branch = "public", int buildId = 0) { appInfo = null; if (Program.Canceled) @@ -101,14 +104,19 @@ namespace CreamInstaller string appUpdatePath = $@"{AppInfoPath}\{appId}"; string appUpdateFile = $@"{appUpdatePath}\appinfo.txt"; restart: + if (Program.Canceled) + { + return false; + } + if (Directory.Exists(appUpdatePath) && File.Exists(appUpdateFile)) { output = File.ReadAllText(appUpdateFile, Encoding.UTF8); } else { - Run($@"+@ShutdownOnFailedCommand 0 +login anonymous +app_info_print {appId} +force_install_dir {appUpdatePath} +app_update 4 +quit", out _); - Run($@"+@ShutdownOnFailedCommand 0 +login anonymous +app_info_print {appId} +quit", out output); + Run($@"+@ShutdownOnFailedCommand 0 +login anonymous +app_info_print {appId} +force_install_dir {appUpdatePath} +app_update 4 +quit"); + output = Run($@"+@ShutdownOnFailedCommand 0 +login anonymous +app_info_print {appId} +quit"); int openBracket = output.IndexOf("{"); int closeBracket = output.LastIndexOf("}"); if (openBracket != -1 && closeBracket != -1) @@ -149,7 +157,6 @@ namespace CreamInstaller { return true; } - if (type is null || int.Parse(buildid) < buildId) { foreach (int id in ParseDlcAppIds(appInfo)) @@ -164,14 +171,13 @@ namespace CreamInstaller { Directory.Delete(appUpdatePath, true); } - goto restart; } } return true; } - public static List ParseDlcAppIds(VProperty appInfo) + internal static List ParseDlcAppIds(VProperty appInfo) { List dlcIds = new(); if (appInfo is not VProperty) @@ -213,17 +219,23 @@ namespace CreamInstaller return dlcIds; } - public static void Kill() + internal static async Task Kill() { + List tasks = new(); foreach (Process process in Process.GetProcessesByName("steamcmd")) { process.Kill(); + tasks.Add(Task.Run(() => process.WaitForExit())); + } + foreach (Task task in tasks) + { + await task; } } - public static void Dispose() + internal static void Dispose() { - Kill(); + Kill().Wait(); if (Directory.Exists(DirectoryPath)) { Directory.Delete(DirectoryPath, true); diff --git a/CreamInstaller/CreamInstaller.csproj b/CreamInstaller/CreamInstaller.csproj index 694fc38..1a3c9db 100644 --- a/CreamInstaller/CreamInstaller.csproj +++ b/CreamInstaller/CreamInstaller.csproj @@ -5,7 +5,7 @@ true Resources\ini.ico true - 2.2.0.0 + 2.2.1.0 Resources\ini.ico Automatically generates and installs CreamAPI files for Steam games on the user's computer. It can also generate and install CreamAPI for the Paradox Launcher should the user select a Paradox Interactive game. diff --git a/CreamInstaller/Forms/Components/CustomForm.cs b/CreamInstaller/Forms/Components/CustomForm.cs new file mode 100644 index 0000000..9e09ac8 --- /dev/null +++ b/CreamInstaller/Forms/Components/CustomForm.cs @@ -0,0 +1,27 @@ +using System.Windows.Forms; + +namespace CreamInstaller +{ + internal class CustomForm : Form + { + internal CustomForm() : base() + { + Icon = Properties.Resources.Icon; + } + + internal CustomForm(IWin32Window owner) : this() + { + Owner = owner as Form; + } + + protected override CreateParams CreateParams // Double buffering for all controls + { + get + { + CreateParams handleParam = base.CreateParams; + handleParam.ExStyle |= 0x02000000; // WS_EX_COMPOSITED + return handleParam; + } + } + } +} diff --git a/CreamInstaller/Forms/Components/CustomTreeView.cs b/CreamInstaller/Forms/Components/CustomTreeView.cs index 803b895..a5c1ddb 100644 --- a/CreamInstaller/Forms/Components/CustomTreeView.cs +++ b/CreamInstaller/Forms/Components/CustomTreeView.cs @@ -4,7 +4,7 @@ using System.Windows.Forms; namespace CreamInstaller { - public class CustomTreeView : TreeView + internal class CustomTreeView : TreeView { protected override void WndProc(ref Message m) { @@ -18,7 +18,7 @@ namespace CreamInstaller } } - public CustomTreeView() : base() + internal CustomTreeView() : base() { DrawMode = TreeViewDrawMode.OwnerDrawAll; DrawNode += new DrawTreeNodeEventHandler(DrawTreeNode); diff --git a/CreamInstaller/Forms/DialogForm.cs b/CreamInstaller/Forms/DialogForm.cs index 5af9e24..bd693f9 100644 --- a/CreamInstaller/Forms/DialogForm.cs +++ b/CreamInstaller/Forms/DialogForm.cs @@ -3,16 +3,14 @@ using System.Windows.Forms; namespace CreamInstaller { - public partial class DialogForm : Form + internal partial class DialogForm : CustomForm { - public DialogForm(IWin32Window owner) + internal DialogForm(IWin32Window owner) : base(owner) { - Owner = owner as Form; InitializeComponent(); - Icon = Properties.Resources.Icon; } - public DialogResult Show(string formName, Icon descriptionIcon, string descriptionText, string acceptButtonText, string cancelButtonText = null) + internal DialogResult Show(string formName, Icon descriptionIcon, string descriptionText, string acceptButtonText, string cancelButtonText = null) { icon.Image = descriptionIcon.ToBitmap(); Text = formName; diff --git a/CreamInstaller/Forms/InstallForm.cs b/CreamInstaller/Forms/InstallForm.cs index 41b2d75..4f01d17 100644 --- a/CreamInstaller/Forms/InstallForm.cs +++ b/CreamInstaller/Forms/InstallForm.cs @@ -10,18 +10,16 @@ using System.Windows.Forms; namespace CreamInstaller { - public partial class InstallForm : Form + internal partial class InstallForm : CustomForm { - public bool Reselecting = false; - public bool Uninstalling = false; + internal bool Reselecting = false; + internal bool Uninstalling = false; - public InstallForm(IWin32Window owner, bool uninstall = false) + internal InstallForm(IWin32Window owner, bool uninstall = false) : base(owner) { - Owner = owner as Form; InitializeComponent(); - Program.InstallForm = this; Text = Program.ApplicationName; - Icon = Properties.Resources.Icon; + Program.InstallForm = this; logTextBox.BackColor = InstallationLog.Background; Uninstalling = uninstall; } @@ -29,7 +27,7 @@ namespace CreamInstaller private int OperationsCount; private int CompleteOperationsCount; - public void UpdateProgress(int progress) + internal void UpdateProgress(int progress) { int value = (int)((float)(CompleteOperationsCount / (float)OperationsCount) * 100) + (progress / OperationsCount); if (value < userProgressBar.Value) @@ -39,7 +37,7 @@ namespace CreamInstaller userProgressBar.Value = value; } - public void UpdateUser(string text, Color color, bool log = true) + internal async Task UpdateUser(string text, Color color, bool log = true) { userInfoLabel.Text = text; if (log && !logTextBox.IsDisposed) @@ -50,6 +48,23 @@ namespace CreamInstaller } logTextBox.AppendText(userInfoLabel.Text, color); } + await Task.Run(() => Thread.Sleep(1)); // to keep the text box control from glitching + } + + internal async Task WriteConfiguration(StreamWriter writer, int steamAppId, string name, SortedList steamDlcApps) + { + writer.WriteLine(); + writer.WriteLine($"; {name}"); + writer.WriteLine("[steam]"); + writer.WriteLine($"appid = {steamAppId}"); + writer.WriteLine(); + writer.WriteLine("[dlc]"); + await UpdateUser($"Added game to cream_api.ini with appid {steamAppId} ({name})", InstallationLog.Resource); + foreach (KeyValuePair dlcApp in steamDlcApps) + { + writer.WriteLine($"{dlcApp.Key} = {dlcApp.Value}"); + await UpdateUser($"Added DLC to cream_api.ini with appid {dlcApp.Key} ({dlcApp.Value})", InstallationLog.Resource); + } } private async Task OperateFor(ProgramSelection selection) @@ -59,7 +74,7 @@ namespace CreamInstaller int cur = 0; foreach (string directory in selection.SteamApiDllDirectories) { - UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} CreamAPI for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); + await UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} CreamAPI for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); if (!Program.IsProgramRunningDialog(this, selection)) { throw new OperationCanceledException(); @@ -76,25 +91,25 @@ namespace CreamInstaller if (File.Exists(api)) { File.Delete(api); - UpdateUser($"Deleted file: {Path.GetFileName(api)}", InstallationLog.Resource); + await UpdateUser($"Deleted file: {Path.GetFileName(api)}", InstallationLog.Resource); } File.Move(api_o, api); - UpdateUser($"Renamed file: {Path.GetFileName(api_o)} -> {Path.GetFileName(api)}", InstallationLog.Resource); + await UpdateUser($"Renamed file: {Path.GetFileName(api_o)} -> {Path.GetFileName(api)}", InstallationLog.Resource); } if (File.Exists(api64_o)) { if (File.Exists(api64)) { File.Delete(api64); - UpdateUser($"Deleted file: {Path.GetFileName(api64)}", InstallationLog.Resource); + await UpdateUser($"Deleted file: {Path.GetFileName(api64)}", InstallationLog.Resource); } File.Move(api64_o, api64); - UpdateUser($"Renamed file: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", InstallationLog.Resource); + await UpdateUser($"Renamed file: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", InstallationLog.Resource); } if (File.Exists(cApi)) { File.Delete(cApi); - UpdateUser($"Deleted file: {Path.GetFileName(cApi)}", InstallationLog.Resource); + await UpdateUser($"Deleted file: {Path.GetFileName(cApi)}", InstallationLog.Resource); } } else @@ -102,60 +117,38 @@ namespace CreamInstaller if (File.Exists(api) && !File.Exists(api_o)) { File.Move(api, api_o); - UpdateUser($"Renamed file: {Path.GetFileName(api)} -> {Path.GetFileName(api_o)}", InstallationLog.Resource); + await UpdateUser($"Renamed file: {Path.GetFileName(api)} -> {Path.GetFileName(api_o)}", InstallationLog.Resource); } if (File.Exists(api_o)) { Properties.Resources.API.Write(api); - UpdateUser($"Wrote resource to file: {Path.GetFileName(api)}", InstallationLog.Resource); + await UpdateUser($"Wrote resource to file: {Path.GetFileName(api)}", InstallationLog.Resource); } if (File.Exists(api64) && !File.Exists(api64_o)) { File.Move(api64, api64_o); - UpdateUser($"Renamed file: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", InstallationLog.Resource); + await UpdateUser($"Renamed file: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", InstallationLog.Resource); } if (File.Exists(api64_o)) { Properties.Resources.API64.Write(api64); - UpdateUser($"Wrote resource to file: {Path.GetFileName(api64)}", InstallationLog.Resource); + await UpdateUser($"Wrote resource to file: {Path.GetFileName(api64)}", InstallationLog.Resource); } - UpdateUser("Generating CreamAPI for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); + await UpdateUser("Generating CreamAPI for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation); File.Create(cApi).Close(); StreamWriter writer = new(cApi, true, Encoding.UTF8); writer.WriteLine("; " + Application.CompanyName + " v" + Application.ProductVersion); if (selection.SteamAppId > 0) { - writer.WriteLine(); - writer.WriteLine($"; {selection.Name}"); - writer.WriteLine("[steam]"); - writer.WriteLine($"appid = {selection.SteamAppId}"); - writer.WriteLine(); - writer.WriteLine("[dlc]"); - UpdateUser($"Added game to cream_api.ini with appid {selection.SteamAppId} ({selection.Name})", InstallationLog.Resource); - foreach (KeyValuePair dlcApp in selection.SelectedSteamDlc) - { - writer.WriteLine($"{dlcApp.Key} = {dlcApp.Value}"); - UpdateUser($"Added DLC to cream_api.ini with appid {dlcApp.Key} ({dlcApp.Value})", InstallationLog.Resource); - } + await WriteConfiguration(writer, selection.SteamAppId, selection.Name, selection.SelectedSteamDlc); } foreach (Tuple> extraAppDlc in selection.ExtraSteamAppIdDlc) { - writer.WriteLine(); - writer.WriteLine("[steam]"); - writer.WriteLine($"appid = {extraAppDlc.Item1}"); - writer.WriteLine(); - writer.WriteLine("[dlc]"); - UpdateUser($"Added game to cream_api.ini with appid {extraAppDlc.Item1} ({extraAppDlc.Item2})", InstallationLog.Resource); - foreach (KeyValuePair dlcApp in extraAppDlc.Item3) - { - writer.WriteLine($"{dlcApp.Key} = {dlcApp.Value}"); - UpdateUser($"Added DLC to cream_api.ini with appid {dlcApp.Key} ({dlcApp.Value})", InstallationLog.Resource); - } + await WriteConfiguration(writer, extraAppDlc.Item1, extraAppDlc.Item2, extraAppDlc.Item3); } writer.Flush(); writer.Close(); } - await Task.Run(() => Thread.Sleep(10)); // to keep the text box control from glitching UpdateProgress(++cur / count * 100); } UpdateProgress(100); @@ -175,16 +168,16 @@ namespace CreamInstaller try { await OperateFor(selection); - UpdateUser($"Operation succeeded for {selection.Name}.", InstallationLog.Success); + await UpdateUser($"Operation succeeded for {selection.Name}.", InstallationLog.Success); selection.Enabled = false; } catch (Exception exception) { - UpdateUser($"Operation failed for {selection.Name}: " + exception.ToString(), InstallationLog.Error); + await UpdateUser($"Operation failed for {selection.Name}: " + exception.ToString(), InstallationLog.Error); } ++CompleteOperationsCount; } - Program.Cleanup(); + await Program.Cleanup(); List FailedSelections = ProgramSelection.AllSafeEnabled; if (FailedSelections.Any()) { @@ -211,11 +204,11 @@ namespace CreamInstaller try { await Operate(); - UpdateUser($"CreamAPI successfully {(Uninstalling ? "uninstalled" : "installed and generated")} for " + ProgramCount + " program(s).", InstallationLog.Success); + await UpdateUser($"CreamAPI successfully {(Uninstalling ? "uninstalled" : "installed and generated")} for " + ProgramCount + " program(s).", InstallationLog.Success); } catch (Exception exception) { - UpdateUser($"CreamAPI {(Uninstalling ? "uninstallation" : "installation and/or generation")} failed: " + exception.ToString(), InstallationLog.Error); + await UpdateUser($"CreamAPI {(Uninstalling ? "uninstallation" : "installation and/or generation")} failed: " + exception.ToString(), InstallationLog.Error); retryButton.Enabled = true; } userProgressBar.Value = userProgressBar.Maximum; @@ -239,31 +232,30 @@ namespace CreamInstaller { goto retry; } - Close(); } } private void OnAccept(object sender, EventArgs e) { - Program.Cleanup(); + Program.Cleanup().Wait(); Close(); } private void OnRetry(object sender, EventArgs e) { - Program.Cleanup(); + Program.Cleanup().Wait(); Start(); } private void OnCancel(object sender, EventArgs e) { - Program.Cleanup(); + Program.Cleanup().Wait(); } private void OnReselect(object sender, EventArgs e) { - Program.Cleanup(); + Program.Cleanup().Wait(); Reselecting = true; Close(); } diff --git a/CreamInstaller/Forms/MainForm.cs b/CreamInstaller/Forms/MainForm.cs index 895a264..62a152a 100644 --- a/CreamInstaller/Forms/MainForm.cs +++ b/CreamInstaller/Forms/MainForm.cs @@ -15,13 +15,12 @@ using System.Windows.Forms; namespace CreamInstaller { - public partial class MainForm : Form + internal partial class MainForm : CustomForm { - public MainForm() + internal MainForm() : base() { InitializeComponent(); Text = Program.ApplicationName; - Icon = Properties.Resources.Icon; } private static CancellationTokenSource cancellationTokenSource; diff --git a/CreamInstaller/Forms/SelectForm.Designer.cs b/CreamInstaller/Forms/SelectForm.Designer.cs index 635b238..f5eb2ef 100644 --- a/CreamInstaller/Forms/SelectForm.Designer.cs +++ b/CreamInstaller/Forms/SelectForm.Designer.cs @@ -43,7 +43,7 @@ namespace CreamInstaller this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel(); this.allCheckBox = new System.Windows.Forms.CheckBox(); this.progressBar1 = new System.Windows.Forms.ProgressBar(); - this.label2 = new System.Windows.Forms.Label(); + this.progressLabel = new System.Windows.Forms.Label(); this.scanButton = new System.Windows.Forms.Button(); this.uninstallButton = new System.Windows.Forms.Button(); this.groupBox1.SuspendLayout(); @@ -208,13 +208,13 @@ namespace CreamInstaller // // label2 // - this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + this.progressLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.label2.Location = new System.Drawing.Point(12, 279); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(760, 15); - this.label2.TabIndex = 10; - this.label2.Text = "Loading . . ."; + this.progressLabel.Location = new System.Drawing.Point(12, 279); + this.progressLabel.Name = "label2"; + this.progressLabel.Size = new System.Drawing.Size(760, 15); + this.progressLabel.TabIndex = 10; + this.progressLabel.Text = "Loading . . ."; // // scanButton // @@ -254,7 +254,7 @@ namespace CreamInstaller this.Controls.Add(this.label1); this.Controls.Add(this.cancelButton); this.Controls.Add(this.installButton); - this.Controls.Add(this.label2); + this.Controls.Add(this.progressLabel); this.DoubleBuffered = true; this.MaximizeBox = false; this.MinimizeBox = false; @@ -280,7 +280,7 @@ namespace CreamInstaller private System.Windows.Forms.Label label1; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.ProgressBar progressBar1; - private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label progressLabel; private System.Windows.Forms.CheckBox allCheckBox; private Button scanButton; private Label noneFoundLabel; diff --git a/CreamInstaller/Forms/SelectForm.cs b/CreamInstaller/Forms/SelectForm.cs index 7713ba5..a49db0f 100644 --- a/CreamInstaller/Forms/SelectForm.cs +++ b/CreamInstaller/Forms/SelectForm.cs @@ -15,15 +15,13 @@ using System.Windows.Forms; namespace CreamInstaller { - public partial class SelectForm : Form + internal partial class SelectForm : CustomForm { - public SelectForm(IWin32Window owner) + internal SelectForm(IWin32Window owner) : base(owner) { - Owner = owner as Form; InitializeComponent(); - Program.SelectForm = this; Text = Program.ApplicationName; - Icon = Properties.Resources.Icon; + Program.SelectForm = this; } private static List GameLibraryDirectories @@ -194,7 +192,7 @@ namespace CreamInstaller internal List RunningTasks = new(); - private void GetCreamApiApplicablePrograms(IProgress progress) + private async Task GetCreamApiApplicablePrograms(IProgress progress) { int cur = 0; if (Program.Canceled) @@ -256,7 +254,7 @@ namespace CreamInstaller continue; } } - Task task = Task.Run(() => + Task task = Task.Run(async () => { if (Program.Canceled || !GetDllDirectoriesFromGameDirectory(directory, out List dllDirectories)) { @@ -350,8 +348,7 @@ namespace CreamInstaller { return; } - - task.Wait(); + await task; } if (Program.Canceled) { @@ -411,8 +408,7 @@ namespace CreamInstaller { return; } - - task.Wait(); + await task; } progress.Report(RunningTasks.Count); } @@ -433,7 +429,7 @@ namespace CreamInstaller uninstallButton.Enabled = installButton.Enabled; selectionTreeView.Enabled = false; - label2.Visible = true; + progressLabel.Visible = true; progressBar1.Visible = true; progressBar1.Value = 0; groupBox1.Size = new(groupBox1.Size.Width, groupBox1.Size.Height - 44); @@ -457,15 +453,15 @@ namespace CreamInstaller int p = Math.Max(Math.Min((int)((float)(curProgress / (float)maxProgress) * 100), 100), 0); if (validating) { - label2.Text = $"Validating . . . {p}% ({curProgress}/{maxProgress})"; + progressLabel.Text = $"Validating . . . {p}% ({curProgress}/{maxProgress})"; } else if (setup) { - label2.Text = $"Setting up SteamCMD . . . {p}% ({curProgress}/{maxProgress})"; + progressLabel.Text = $"Setting up SteamCMD . . . {p}% ({curProgress}/{maxProgress})"; } else { - label2.Text = $"Gathering and caching your applicable games and their DLCs . . . {p}% ({curProgress}/{maxProgress})"; + progressLabel.Text = $"Gathering and caching your applicable games and their DLCs . . . {p}% ({curProgress}/{maxProgress})"; } progressBar1.Value = p; @@ -476,7 +472,7 @@ namespace CreamInstaller iProgress.Report(cur); if (!validating) { - label2.Text = "Setting up SteamCMD . . . "; + progressLabel.Text = "Setting up SteamCMD . . . "; } if (!Directory.Exists(SteamCMD.DirectoryPath)) @@ -489,16 +485,16 @@ namespace CreamInstaller watcher.Filter = "*"; watcher.IncludeSubdirectories = true; watcher.EnableRaisingEvents = true; - await Task.Run(() => SteamCMD.Setup()); + await SteamCMD.Setup(); watcher.Dispose(); setup = false; if (!validating) { - label2.Text = "Gathering and caching your applicable games and their DLCs . . . "; + progressLabel.Text = "Gathering and caching your applicable games and their DLCs . . . "; } - await Task.Run(() => GetCreamApiApplicablePrograms(iProgress)); + await GetCreamApiApplicablePrograms(iProgress); ProgramSelection.ValidateAll(); TreeNodes.ForEach(node => { @@ -510,7 +506,7 @@ namespace CreamInstaller progressBar1.Value = 100; groupBox1.Size = new(groupBox1.Size.Width, groupBox1.Size.Height + 44); - label2.Visible = false; + progressLabel.Visible = false; progressBar1.Visible = false; selectionTreeView.Enabled = ProgramSelection.All.Any(); @@ -525,7 +521,7 @@ namespace CreamInstaller blockedGamesCheckBox.Enabled = true; blockProtectedHelpButton.Enabled = true; - label2.Text = "Validating . . . "; + progressLabel.Text = "Validating . . . "; if (!validating && !Program.Canceled) { OnLoad(true); @@ -597,9 +593,9 @@ namespace CreamInstaller selectionTreeView.NodeMouseClick += (sender, e) => { TreeNode node = e.Node; - string appId = node.Name; if (e.Button == MouseButtons.Right && node.Bounds.Contains(e.Location)) { + string appId = node.Name; if (appId != "0") { Process.Start(new ProcessStartInfo @@ -718,7 +714,11 @@ namespace CreamInstaller private void OnCancel(object sender, EventArgs e) { - Program.Cleanup(); + progressLabel.Text = "Cancelling . . . "; + Task.Run(async () => + { + await Program.Cleanup(); + }); } private void OnAllCheckBoxChanged(object sender, EventArgs e) diff --git a/CreamInstaller/Program.cs b/CreamInstaller/Program.cs index 45b25f5..d4b4549 100644 --- a/CreamInstaller/Program.cs +++ b/CreamInstaller/Program.cs @@ -5,23 +5,24 @@ using System.Drawing; using System.IO; using System.Reflection; using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; namespace CreamInstaller { - public static class Program + internal static class Program { - public static readonly string ApplicationName = Application.CompanyName + " v" + Application.ProductVersion + ": " + Application.ProductName; - public static readonly Assembly EntryAssembly = Assembly.GetEntryAssembly(); - public static readonly Process CurrentProcess = Process.GetCurrentProcess(); - public static readonly string CurrentProcessFilePath = CurrentProcess.MainModule.FileName; - public static readonly string CurrentProcessDirectory = CurrentProcessFilePath.Substring(0, CurrentProcessFilePath.LastIndexOf("\\")); - public static readonly string BackupFileExtension = ".creaminstaller.backup"; + internal static readonly string ApplicationName = Application.CompanyName + " v" + Application.ProductVersion + ": " + Application.ProductName; + internal static readonly Assembly EntryAssembly = Assembly.GetEntryAssembly(); + internal static readonly Process CurrentProcess = Process.GetCurrentProcess(); + internal static readonly string CurrentProcessFilePath = CurrentProcess.MainModule.FileName; + internal static readonly string CurrentProcessDirectory = CurrentProcessFilePath.Substring(0, CurrentProcessFilePath.LastIndexOf("\\")); + internal static readonly string BackupFileExtension = ".creaminstaller.backup"; - public static bool BlockProtectedGames = true; - public static readonly string[] ProtectedGameNames = { "PAYDAY 2", "Call to Arms" }; // non-functioning CreamAPI or DLL detections - public static readonly string[] ProtectedGameDirectories = { @"\EasyAntiCheat", @"\BattlEye" }; // DLL detections - public static readonly string[] ProtectedGameDirectoryExceptions = { "Arma 3" }; // Arma 3's BattlEye doesn't detect DLL changes? + internal static bool BlockProtectedGames = true; + internal static readonly string[] ProtectedGameNames = { "PAYDAY 2", "Call to Arms" }; // non-functioning CreamAPI or DLL detections + internal static readonly string[] ProtectedGameDirectories = { @"\EasyAntiCheat", @"\BattlEye" }; // DLL detections + internal static readonly string[] ProtectedGameDirectoryExceptions = { "Arma 3" }; // Arma 3's BattlEye doesn't detect DLL changes? [STAThread] private static void Main() @@ -52,7 +53,7 @@ namespace CreamInstaller mutex.Close(); } - public static bool IsProgramRunningDialog(Form form, ProgramSelection selection) + internal static bool IsProgramRunningDialog(Form form, ProgramSelection selection) { if (selection.AreSteamApiDllsLocked) { @@ -71,7 +72,7 @@ namespace CreamInstaller return false; } - public static bool IsFilePathLocked(this string filePath) + internal static bool IsFilePathLocked(this string filePath) { try { File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None).Close(); } catch (FileNotFoundException) { return false; } @@ -79,22 +80,22 @@ namespace CreamInstaller return false; } - public static SelectForm SelectForm; - public static InstallForm InstallForm; + internal static SelectForm SelectForm; + internal static InstallForm InstallForm; - public static List ProgramSelections = new(); + internal static List ProgramSelections = new(); - public static bool Canceled = false; + internal static bool Canceled = false; - public static void Cleanup(bool cancel = true) + internal static async Task Cleanup(bool cancel = true) { Canceled = cancel; - SteamCMD.Kill(); + await SteamCMD.Kill(); } private static void OnApplicationExit(object s, EventArgs e) { - Cleanup(); + Cleanup().Wait(); } internal static void InheritLocation(this Form form, Form fromForm) diff --git a/CreamInstaller/Resources/FileResourceExtensions.cs b/CreamInstaller/Resources/FileResourceExtensions.cs index c3662c1..c0c43fb 100644 --- a/CreamInstaller/Resources/FileResourceExtensions.cs +++ b/CreamInstaller/Resources/FileResourceExtensions.cs @@ -2,9 +2,9 @@ namespace CreamInstaller { - public static class FileResourceExtensions + internal static class FileResourceExtensions { - public static void Write(this byte[] resource, string filePath) + internal static void Write(this byte[] resource, string filePath) { using FileStream file = new(filePath, FileMode.Create, FileAccess.Write); file.Write(resource);