- 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
This commit is contained in:
pointfeev 2022-01-21 16:10:15 -05:00
parent 40ba6ab448
commit b3526c7fbf
14 changed files with 210 additions and 181 deletions

View file

@ -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;
}

View file

@ -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;

View file

@ -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<string> SteamApiDllDirectories;
internal string Name;
internal string RootDirectory;
internal int SteamAppId;
internal List<string> SteamApiDllDirectories;
public VProperty AppInfo = null;
internal VProperty AppInfo = null;
public readonly SortedList<int, string> AllSteamDlc = new();
public readonly SortedList<int, string> SelectedSteamDlc = new();
public readonly List<Tuple<int, string, SortedList<int, string>>> ExtraSteamAppIdDlc = new();
internal readonly SortedList<int, string> AllSteamDlc = new();
internal readonly SortedList<int, string> SelectedSteamDlc = new();
internal readonly List<Tuple<int, string, SortedList<int, string>>> 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<int, string> 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<ProgramSelection> All => Program.ProgramSelections;
internal static List<ProgramSelection> All => Program.ProgramSelections;
public static List<ProgramSelection> AllSafe => All.FindAll(s => s.Usable);
internal static List<ProgramSelection> AllSafe => All.FindAll(s => s.Usable);
public static List<ProgramSelection> AllSafeEnabled => AllSafe.FindAll(s => s.Enabled);
internal static List<ProgramSelection> 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<int, string>? GetDlcFromAppId(int appId)
internal static KeyValuePair<int, string>? GetDlcFromAppId(int appId)
{
foreach (ProgramSelection selection in AllSafe)
{

View file

@ -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<string> 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<int> ParseDlcAppIds(VProperty appInfo)
internal static List<int> ParseDlcAppIds(VProperty appInfo)
{
List<int> 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<Task> 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);

View file

@ -5,7 +5,7 @@
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>Resources\ini.ico</ApplicationIcon>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
<Version>2.2.0.0</Version>
<Version>2.2.1.0</Version>
<PackageIcon>Resources\ini.ico</PackageIcon>
<PackageIconUrl />
<Description>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.</Description>

View file

@ -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;
}
}
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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<int, string> 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<int, string> 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<int, string> 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<int, string, SortedList<int, string>> 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<int, string> 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<ProgramSelection> 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();
}

View file

@ -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;

View file

@ -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;

View file

@ -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<string> GameLibraryDirectories
@ -194,7 +192,7 @@ namespace CreamInstaller
internal List<Task> RunningTasks = new();
private void GetCreamApiApplicablePrograms(IProgress<int> progress)
private async Task GetCreamApiApplicablePrograms(IProgress<int> 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<string> 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)

View file

@ -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<ProgramSelection> ProgramSelections = new();
internal static List<ProgramSelection> 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)

View file

@ -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);