- Large refactoring & fixes
- Program forms are no longer TopMost
This commit is contained in:
pointfeev 2022-05-17 14:41:35 -05:00
parent 0c64a64bf3
commit 023df98fcc
17 changed files with 143 additions and 195 deletions

View file

@ -41,9 +41,9 @@ internal class CustomForm : Form
using Bitmap bitmap = new(Size.Width - 14, Size.Height - 7); using Bitmap bitmap = new(Size.Width - 14, Size.Height - 7);
using Graphics graphics = Graphics.FromImage(bitmap); using Graphics graphics = Graphics.FromImage(bitmap);
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
ImageCodecInfo jpeg = ImageCodecInfo.GetImageEncoders()[1];
using EncoderParameters encoding = new(1); using EncoderParameters encoding = new(1);
encoding.Param[0] = new(Encoder.Quality, 100L); using EncoderParameter encoderParam = new(Encoder.Quality, 100L);
encoding.Param[0] = encoderParam;
graphics.CopyFromScreen(new(bounds.Left + 7, bounds.Top), Point.Empty, new(Size.Width - 14, Size.Height - 7)); graphics.CopyFromScreen(new(bounds.Left + 7, bounds.Top), Point.Empty, new(Size.Width - 14, Size.Height - 7));
Clipboard.SetImage(bitmap); Clipboard.SetImage(bitmap);
e.Handled = true; e.Handled = true;

View file

@ -5,7 +5,7 @@
<UseWindowsForms>True</UseWindowsForms> <UseWindowsForms>True</UseWindowsForms>
<ApplicationIcon>Resources\ini.ico</ApplicationIcon> <ApplicationIcon>Resources\ini.ico</ApplicationIcon>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract> <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
<Version>3.5.0.1</Version> <Version>3.5.0.2</Version>
<PackageIcon>Resources\ini.ico</PackageIcon> <PackageIcon>Resources\ini.ico</PackageIcon>
<PackageLicenseFile>LICENSE</PackageLicenseFile> <PackageLicenseFile>LICENSE</PackageLicenseFile>
<Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright> <Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright>

View file

@ -134,7 +134,6 @@ namespace CreamInstaller
this.Name = "DialogForm"; this.Name = "DialogForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "DialogForm"; this.Text = "DialogForm";
this.TopMost = true;
((System.ComponentModel.ISupportInitialize)(this.icon)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.icon)).EndInit();
this.descriptionPanel.ResumeLayout(false); this.descriptionPanel.ResumeLayout(false);
this.descriptionPanel.PerformLayout(); this.descriptionPanel.PerformLayout();

View file

@ -144,7 +144,6 @@ namespace CreamInstaller
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show; this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "InstallForm"; this.Text = "InstallForm";
this.TopMost = true;
this.Load += new System.EventHandler(this.OnLoad); this.Load += new System.EventHandler(this.OnLoad);
this.ResumeLayout(false); this.ResumeLayout(false);

View file

@ -18,7 +18,7 @@ namespace CreamInstaller;
internal partial class InstallForm : CustomForm internal partial class InstallForm : CustomForm
{ {
internal bool Reselecting; internal bool Reselecting;
internal bool Uninstalling; internal readonly bool Uninstalling;
internal InstallForm(IWin32Window owner, bool uninstall = false) : base(owner) internal InstallForm(IWin32Window owner, bool uninstall = false) : base(owner)
{ {
@ -36,7 +36,7 @@ internal partial class InstallForm : CustomForm
if (!userProgressBar.Disposing && !userProgressBar.IsDisposed) if (!userProgressBar.Disposing && !userProgressBar.IsDisposed)
userProgressBar.Invoke(() => userProgressBar.Invoke(() =>
{ {
int value = (int)((float)(CompleteOperationsCount / (float)OperationsCount) * 100) + progress / OperationsCount; int value = (int)((float)CompleteOperationsCount / OperationsCount * 100) + progress / OperationsCount;
if (value < userProgressBar.Value) return; if (value < userProgressBar.Value) return;
userProgressBar.Value = value; userProgressBar.Value = value;
}); });
@ -374,7 +374,7 @@ internal partial class InstallForm : CustomForm
} }
catch (Exception exception) catch (Exception exception)
{ {
UpdateUser($"Operation failed for {selection.Name}: " + exception.ToString(), InstallationLog.Error); UpdateUser($"Operation failed for {selection.Name}: " + exception, InstallationLog.Error);
} }
++CompleteOperationsCount; ++CompleteOperationsCount;
} }
@ -403,7 +403,7 @@ internal partial class InstallForm : CustomForm
} }
catch (Exception exception) catch (Exception exception)
{ {
UpdateUser($"SmokeAPI/ScreamAPI {(Uninstalling ? "uninstallation" : "installation and/or generation")} failed: " + exception.ToString(), InstallationLog.Error); UpdateUser($"SmokeAPI/ScreamAPI {(Uninstalling ? "uninstallation" : "installation and/or generation")} failed: " + exception, InstallationLog.Error);
retryButton.Enabled = true; retryButton.Enabled = true;
} }
userProgressBar.Value = userProgressBar.Maximum; userProgressBar.Value = userProgressBar.Maximum;

View file

@ -13,19 +13,6 @@ namespace CreamInstaller
/// </summary> /// </summary>
private System.ComponentModel.IContainer components = null; private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code #region Windows Form Designer generated code
/// <summary> /// <summary>
@ -109,7 +96,6 @@ namespace CreamInstaller
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "MainForm"; this.Text = "MainForm";
this.TopMost = true;
this.Load += new System.EventHandler(this.OnLoad); this.Load += new System.EventHandler(this.OnLoad);
this.ResumeLayout(false); this.ResumeLayout(false);

View file

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
@ -26,7 +27,7 @@ internal partial class MainForm : CustomForm
Text = Program.ApplicationNameShort; Text = Program.ApplicationNameShort;
} }
private static CancellationTokenSource cancellationTokenSource; private CancellationTokenSource cancellationTokenSource;
private void StartProgram() private void StartProgram()
{ {
@ -42,9 +43,9 @@ internal partial class MainForm : CustomForm
Close(); Close();
} }
private static UpdateManager updateManager; private UpdateManager updateManager;
private static Version latestVersion; private Version latestVersion;
private static IReadOnlyList<Version> versions; private IReadOnlyList<Version> versions;
private async void OnLoad() private async void OnLoad()
{ {
@ -93,32 +94,31 @@ internal partial class MainForm : CustomForm
updateButton.Click += new(OnUpdate); updateButton.Click += new(OnUpdate);
changelogTreeView.Visible = true; changelogTreeView.Visible = true;
Version currentVersion = new(Application.ProductVersion); Version currentVersion = new(Application.ProductVersion);
foreach (Version version in versions) foreach (Version version in versions.Where(v => v > currentVersion && !changelogTreeView.Nodes.ContainsKey(v.ToString())))
if (version > currentVersion && !changelogTreeView.Nodes.ContainsKey(version.ToString())) {
TreeNode root = new($"v{version}");
root.Name = root.Text;
changelogTreeView.Nodes.Add(root);
if (changelogTreeView.Nodes.Count > 0) changelogTreeView.Nodes[0].EnsureVisible();
_ = Task.Run(async () =>
{ {
TreeNode root = new($"v{version}"); HtmlNodeCollection nodes = await HttpClientManager.GetDocumentNodes(
root.Name = root.Text; $"https://github.com/pointfeev/CreamInstaller/releases/tag/v{version}",
changelogTreeView.Nodes.Add(root); "//div[@data-test-selector='body-content']/ul/li");
if (changelogTreeView.Nodes.Count > 0) changelogTreeView.Nodes[0].EnsureVisible(); if (nodes is null) changelogTreeView.Nodes.Remove(root);
_ = Task.Run(async () => else foreach (HtmlNode node in nodes)
{ {
HtmlNodeCollection nodes = await HttpClientManager.GetDocumentNodes( Program.Invoke(changelogTreeView, delegate
$"https://github.com/pointfeev/CreamInstaller/releases/tag/v{version}",
"//div[@data-test-selector='body-content']/ul/li");
if (nodes is null) changelogTreeView.Nodes.Remove(root);
else foreach (HtmlNode node in nodes)
{ {
Program.Invoke(changelogTreeView, delegate TreeNode change = new();
{ change.Text = HttpUtility.HtmlDecode(node.InnerText);
TreeNode change = new(); root.Nodes.Add(change);
change.Text = HttpUtility.HtmlDecode(node.InnerText); root.Expand();
root.Nodes.Add(change); if (changelogTreeView.Nodes.Count > 0) changelogTreeView.Nodes[0].EnsureVisible();
root.Expand(); });
if (changelogTreeView.Nodes.Count > 0) changelogTreeView.Nodes[0].EnsureVisible(); }
}); });
} }
});
}
} }
} }
@ -193,4 +193,13 @@ internal partial class MainForm : CustomForm
updateManager.Dispose(); updateManager.Dispose();
updateManager = null; updateManager = null;
} }
protected override void Dispose(bool disposing)
{
if (disposing && components is not null)
components.Dispose();
base.Dispose(disposing);
cancellationTokenSource?.Dispose();
updateManager?.Dispose();
}
} }

View file

@ -175,7 +175,6 @@ namespace CreamInstaller
this.Name = "SelectDialogForm"; this.Name = "SelectDialogForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "SelectDialogForm"; this.Text = "SelectDialogForm";
this.TopMost = true;
this.groupBox.ResumeLayout(false); this.groupBox.ResumeLayout(false);
this.groupBox.PerformLayout(); this.groupBox.PerformLayout();
this.flowLayoutPanel2.ResumeLayout(false); this.flowLayoutPanel2.ResumeLayout(false);

View file

@ -72,9 +72,8 @@ internal partial class SelectDialogForm : CustomForm
private void OnAllCheckBoxChanged(object sender, EventArgs e) private void OnAllCheckBoxChanged(object sender, EventArgs e)
{ {
bool shouldCheck = false; bool shouldCheck = false;
foreach (TreeNode node in selectionTreeView.Nodes) if (selectionTreeView.Nodes.Cast<TreeNode>().Any(n => !n.Checked))
if (!node.Checked) shouldCheck = true;
shouldCheck = true;
foreach (TreeNode node in selectionTreeView.Nodes) foreach (TreeNode node in selectionTreeView.Nodes)
{ {
node.Checked = shouldCheck; node.Checked = shouldCheck;
@ -98,9 +97,8 @@ internal partial class SelectDialogForm : CustomForm
private void OnSave(object sender, EventArgs e) private void OnSave(object sender, EventArgs e)
{ {
List<string> choices = new(); List<string> choices = new();
foreach (TreeNode node in selectionTreeView.Nodes) foreach (TreeNode node in selectionTreeView.Nodes.Cast<TreeNode>().Where(n => n.Checked))
if (node.Checked) choices.Add(node.Name);
choices.Add(node.Name);
ProgramData.WriteChoices(choices); ProgramData.WriteChoices(choices);
loadButton.Enabled = File.Exists(ProgramData.ChoicesPath); loadButton.Enabled = File.Exists(ProgramData.ChoicesPath);
} }

View file

@ -289,7 +289,6 @@ namespace CreamInstaller
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show; this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "SelectForm"; this.Text = "SelectForm";
this.TopMost = true;
this.Load += new System.EventHandler(this.OnLoad); this.Load += new System.EventHandler(this.OnLoad);
this.groupBox1.ResumeLayout(false); this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout(); this.groupBox1.PerformLayout();

View file

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
@ -226,8 +227,8 @@ internal partial class SelectForm : CustomForm
selection.DllDirectories = dllDirectories; selection.DllDirectories = dllDirectories;
selection.IsSteam = true; selection.IsSteam = true;
selection.ProductUrl = "https://store.steampowered.com/app/" + appId; selection.ProductUrl = "https://store.steampowered.com/app/" + appId;
selection.IconUrl = IconGrabber.SteamAppImagesPath + @$"\{appId}\{appInfo?.Value?.GetChild("common")?.GetChild("icon")?.ToString()}.jpg"; selection.IconUrl = IconGrabber.SteamAppImagesPath + @$"\{appId}\{appInfo?.Value?.GetChild("common")?.GetChild("icon")}.jpg";
selection.SubIconUrl = appData?.header_image ?? IconGrabber.SteamAppImagesPath + @$"\{appId}\{appInfo?.Value?.GetChild("common")?.GetChild("clienticon")?.ToString()}.ico"; selection.SubIconUrl = appData?.header_image ?? IconGrabber.SteamAppImagesPath + @$"\{appId}\{appInfo?.Value?.GetChild("common")?.GetChild("clienticon")}.ico";
selection.Publisher = appData?.publishers[0] ?? appInfo?.Value?.GetChild("extended")?.GetChild("publisher")?.ToString(); selection.Publisher = appData?.publishers[0] ?? appInfo?.Value?.GetChild("extended")?.GetChild("publisher")?.ToString();
if (Program.Canceled) return; if (Program.Canceled) return;
@ -421,9 +422,8 @@ internal partial class SelectForm : CustomForm
if (!Program.IsGameBlocked(name, gameDirectory)) if (!Program.IsGameBlocked(name, gameDirectory))
gameChoices.Add(("Steam", appId, name, ProgramsToScan is not null && ProgramsToScan.Any(p => p.id == appId))); gameChoices.Add(("Steam", appId, name, ProgramsToScan is not null && ProgramsToScan.Any(p => p.id == appId)));
if (Directory.Exists(EpicLibrary.EpicManifestsPath)) if (Directory.Exists(EpicLibrary.EpicManifestsPath))
foreach (Manifest manifest in await EpicLibrary.GetGames()) foreach (Manifest manifest in (await EpicLibrary.GetGames()).Where(m => !Program.IsGameBlocked(m.DisplayName, m.InstallLocation)))
if (!Program.IsGameBlocked(manifest.DisplayName, manifest.InstallLocation)) gameChoices.Add(("Epic", manifest.CatalogNamespace, manifest.DisplayName, ProgramsToScan is not null && ProgramsToScan.Any(p => p.id == manifest.CatalogNamespace)));
gameChoices.Add(("Epic", manifest.CatalogNamespace, manifest.DisplayName, ProgramsToScan is not null && ProgramsToScan.Any(p => p.id == manifest.CatalogNamespace)));
if (gameChoices.Any()) if (gameChoices.Any())
{ {
using SelectDialogForm form = new(this); using SelectDialogForm form = new(this);
@ -455,7 +455,7 @@ internal partial class SelectForm : CustomForm
Thread.Sleep(0); Thread.Sleep(0);
if (_progress < 0 || _progress > maxProgress) maxProgress = -_progress; if (_progress < 0 || _progress > maxProgress) maxProgress = -_progress;
else curProgress = _progress; else curProgress = _progress;
int p = Math.Max(Math.Min((int)((float)(curProgress / (float)maxProgress) * 100), 100), 0); int p = Math.Max(Math.Min((int)((float)curProgress / maxProgress * 100), 100), 0);
progressLabel.Text = setup ? $"Setting up SteamCMD . . . {p}%" progressLabel.Text = setup ? $"Setting up SteamCMD . . . {p}%"
: $"Gathering and caching your applicable games and their DLCs . . . {p}%"; : $"Gathering and caching your applicable games and their DLCs . . . {p}%";
progressBar.Value = p; progressBar.Value = p;
@ -598,7 +598,8 @@ internal partial class SelectForm : CustomForm
(string gameAppId, (DlcType type, string name, string icon) app)? dlc = null; (string gameAppId, (DlcType type, string name, string icon) app)? dlc = null;
if (selection is null) dlc = ProgramSelection.GetDlcFromId(id); if (selection is null) dlc = ProgramSelection.GetDlcFromId(id);
ProgramSelection dlcParentSelection = null; ProgramSelection dlcParentSelection = null;
if (dlc is not null) dlcParentSelection = ProgramSelection.FromId(dlc.Value.gameAppId); if (dlc is not null)
dlcParentSelection = ProgramSelection.FromId(dlc.Value.gameAppId);
if (selection is null && dlcParentSelection is null) if (selection is null && dlcParentSelection is null)
return; return;
ContextMenuItem header = null; ContextMenuItem header = null;
@ -606,7 +607,7 @@ internal partial class SelectForm : CustomForm
header = new(node.Text, "Paradox Launcher"); header = new(node.Text, "Paradox Launcher");
else if (selection is not null) else if (selection is not null)
header = new(node.Text, (id, selection.IconUrl, false)); header = new(node.Text, (id, selection.IconUrl, false));
else if (dlc is not null) else if (dlc is not null && dlcParentSelection is not null)
header = new(node.Text, (id, dlc.Value.app.icon, false), (id, dlcParentSelection.IconUrl, false)); header = new(node.Text, (id, dlc.Value.app.icon, false), (id, dlcParentSelection.IconUrl, false));
contextMenuStrip.Items.Add(header ?? new ContextMenuItem(node.Text)); contextMenuStrip.Items.Add(header ?? new ContextMenuItem(node.Text));
string appInfoVDF = $@"{SteamCMD.AppInfoPath}\{id}.vdf"; string appInfoVDF = $@"{SteamCMD.AppInfoPath}\{id}.vdf";
@ -783,15 +784,15 @@ internal partial class SelectForm : CustomForm
private readonly string helpButtonListPrefix = "\n • "; private readonly string helpButtonListPrefix = "\n • ";
private void OnBlockProtectedGamesHelpButtonClicked(object sender, EventArgs e) private void OnBlockProtectedGamesHelpButtonClicked(object sender, EventArgs e)
{ {
string blockedGames = ""; StringBuilder blockedGames = new();
foreach (string name in Program.ProtectedGames) foreach (string name in Program.ProtectedGames)
blockedGames += helpButtonListPrefix + name; blockedGames.Append(helpButtonListPrefix + name);
string blockedDirectories = ""; StringBuilder blockedDirectories = new();
foreach (string path in Program.ProtectedGameDirectories) foreach (string path in Program.ProtectedGameDirectories)
blockedDirectories += helpButtonListPrefix + path; blockedDirectories.Append(helpButtonListPrefix + path);
string blockedDirectoryExceptions = ""; StringBuilder blockedDirectoryExceptions = new();
foreach (string name in Program.ProtectedGameDirectoryExceptions) foreach (string name in Program.ProtectedGameDirectoryExceptions)
blockedDirectoryExceptions += helpButtonListPrefix + name; blockedDirectoryExceptions.Append(helpButtonListPrefix + name);
using DialogForm form = new(this); using DialogForm form = new(this);
form.Show(SystemIcons.Information, form.Show(SystemIcons.Information,
"Blocks the program from caching and displaying games protected by DLL checks," + "Blocks the program from caching and displaying games protected by DLL checks," +

View file

@ -29,17 +29,11 @@ internal static class ParadoxLauncher
if (paradoxLauncher is not null) if (paradoxLauncher is not null)
{ {
paradoxLauncher.ExtraDlc.Clear(); paradoxLauncher.ExtraDlc.Clear();
foreach (ProgramSelection selection in ProgramSelection.AllEnabled) foreach (ProgramSelection selection in ProgramSelection.AllEnabled.Where(s => s != paradoxLauncher && s.Publisher == "Paradox Interactive"))
{
if (selection == paradoxLauncher || selection.Publisher != "Paradox Interactive") continue;
paradoxLauncher.ExtraDlc.Add(new(selection.Id, selection.Name, selection.SelectedDlc)); paradoxLauncher.ExtraDlc.Add(new(selection.Id, selection.Name, selection.SelectedDlc));
}
if (!paradoxLauncher.ExtraDlc.Any()) if (!paradoxLauncher.ExtraDlc.Any())
foreach (ProgramSelection selection in ProgramSelection.AllSafe) foreach (ProgramSelection selection in ProgramSelection.AllSafe.Where(s => s != paradoxLauncher && s.Publisher == "Paradox Interactive"))
{
if (selection == paradoxLauncher || selection.Publisher != "Paradox Interactive") continue;
paradoxLauncher.ExtraDlc.Add(new(selection.Id, selection.Name, selection.AllDlc)); paradoxLauncher.ExtraDlc.Add(new(selection.Id, selection.Name, selection.AllDlc));
}
} }
} }

View file

@ -114,7 +114,7 @@ internal class ProgramSelection
internal static void ValidateAll(List<(string platform, string id, string name)> programsToScan) => AllSafe.ForEach(selection => selection.Validate(programsToScan)); internal static void ValidateAll(List<(string platform, string id, string name)> programsToScan) => AllSafe.ForEach(selection => selection.Validate(programsToScan));
internal static List<ProgramSelection> All = new(); internal static readonly List<ProgramSelection> All = new();
internal static List<ProgramSelection> AllSafe => All.ToList(); internal static List<ProgramSelection> AllSafe => All.ToList();
@ -125,8 +125,8 @@ internal class ProgramSelection
internal static (string gameId, (DlcType type, string name, string icon) app)? GetDlcFromId(string dlcId) internal static (string gameId, (DlcType type, string name, string icon) app)? GetDlcFromId(string dlcId)
{ {
foreach (ProgramSelection selection in AllSafe) foreach (ProgramSelection selection in AllSafe)
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in selection.AllDlc) foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in selection.AllDlc.Where(p => p.Key == dlcId))
if (pair.Key == dlcId) return (selection.Id, pair.Value); return (selection.Id, pair.Value);
return null; return null;
} }
} }

View file

@ -51,7 +51,6 @@ internal static class SteamCMD
AttemptCount[appId] = 0; AttemptCount[appId] = 0;
} }
if (Program.Canceled) return ""; if (Program.Canceled) return "";
List<string> logs = new();
ProcessStartInfo processStartInfo = new() ProcessStartInfo processStartInfo = new()
{ {
FileName = FilePath, FileName = FilePath,
@ -66,8 +65,8 @@ internal static class SteamCMD
StandardErrorEncoding = Encoding.UTF8 StandardErrorEncoding = Encoding.UTF8
}; };
Process process = Process.Start(processStartInfo); Process process = Process.Start(processStartInfo);
string output = ""; StringBuilder output = new();
string appInfo = ""; StringBuilder appInfo = new();
bool appInfoStarted = false; bool appInfoStarted = false;
DateTime lastOutput = DateTime.UtcNow; DateTime lastOutput = DateTime.UtcNow;
while (true) while (true)
@ -85,8 +84,8 @@ internal static class SteamCMD
lastOutput = DateTime.UtcNow; lastOutput = DateTime.UtcNow;
char ch = (char)c; char ch = (char)c;
if (ch == '{') appInfoStarted = true; if (ch == '{') appInfoStarted = true;
if (appInfoStarted) appInfo += ch; if (appInfoStarted) appInfo.Append(ch);
else output += ch; else output.Append(ch);
} }
DateTime now = DateTime.UtcNow; DateTime now = DateTime.UtcNow;
TimeSpan timeDiff = now - lastOutput; TimeSpan timeDiff = now - lastOutput;
@ -94,20 +93,20 @@ internal static class SteamCMD
{ {
process.Kill(true); process.Kill(true);
process.Close(); process.Close();
if (output.Contains($"No app info for AppID {appId} found, requesting...")) if (output.ToString().Contains($"No app info for AppID {appId} found, requesting..."))
{ {
AttemptCount[appId]++; AttemptCount[appId]++;
processStartInfo.Arguments = GetArguments(appId); processStartInfo.Arguments = GetArguments(appId);
process = Process.Start(processStartInfo); process = Process.Start(processStartInfo);
appInfoStarted = false; appInfoStarted = false;
output = ""; output.Clear();
appInfo = ""; appInfo.Clear();
} }
else break; else break;
} }
} }
Interlocked.Decrement(ref locks[i]); Interlocked.Decrement(ref locks[i]);
return appInfo ?? ""; return appInfo.ToString();
} }
Thread.Sleep(200); Thread.Sleep(200);
} }
@ -118,7 +117,7 @@ internal static class SteamCMD
internal static readonly string ArchivePath = DirectoryPath + @"\steamcmd.zip"; internal static readonly string ArchivePath = DirectoryPath + @"\steamcmd.zip";
internal static readonly string DllPath = DirectoryPath + @"\steamclient.dll"; internal static readonly string DllPath = DirectoryPath + @"\steamclient.dll";
internal static async Task Setup(IProgress<int> progress = null) internal static async Task Setup(IProgress<int> progress)
{ {
await Cleanup(); await Cleanup();
if (!File.Exists(FilePath)) if (!File.Exists(FilePath))
@ -157,56 +156,26 @@ internal static class SteamCMD
if (!Directory.Exists(DirectoryPath)) return; if (!Directory.Exists(DirectoryPath)) return;
await Kill(); await Kill();
try try
{
string[] ntfsFiles = Directory.GetFiles(DirectoryPath, "*.ntfs_transaction_failed");
foreach (string file in ntfsFiles) File.Delete(file);
}
catch { }
try
{ {
if (Directory.Exists(ConfigPath)) if (Directory.Exists(ConfigPath))
{ foreach (string file in Directory.GetFiles(ConfigPath, "*.tmp"))
string[] tmpFiles = Directory.GetFiles(ConfigPath, "*.tmp"); File.Delete(file);
foreach (string file in tmpFiles) File.Delete(file); foreach (string file in Directory.GetFiles(DirectoryPath, "*.old"))
} File.Delete(file);
} foreach (string file in Directory.GetFiles(DirectoryPath, "*.delete"))
catch { } File.Delete(file);
try foreach (string file in Directory.GetFiles(DirectoryPath, "*.crash"))
{ File.Delete(file);
string[] oldFiles = Directory.GetFiles(DirectoryPath, "*.old"); foreach (string file in Directory.GetFiles(DirectoryPath, "*.ntfs_transaction_failed"))
foreach (string file in oldFiles) File.Delete(file); File.Delete(file);
} if (Directory.Exists(AppCachePath))
catch { } Directory.Delete(AppCachePath, true); // this is definitely needed, so SteamCMD gets the latest information for us
try if (Directory.Exists(DumpsPath))
{ Directory.Delete(DumpsPath, true);
string[] deleteFiles = Directory.GetFiles(DirectoryPath, "*.delete"); if (Directory.Exists(LogsPath))
foreach (string file in deleteFiles) File.Delete(file); Directory.Delete(LogsPath, true);
} if (Directory.Exists(SteamAppsPath))
catch { } Directory.Delete(SteamAppsPath, true); // this is just a useless folder created from +app_update 4
try
{
string[] crashFiles = Directory.GetFiles(DirectoryPath, "*.crash");
foreach (string file in crashFiles) File.Delete(file);
}
catch { }
try
{
if (Directory.Exists(AppCachePath)) Directory.Delete(AppCachePath, true); // this is definitely needed, so SteamCMD gets the latest information for us
}
catch { }
try
{
if (Directory.Exists(DumpsPath)) Directory.Delete(DumpsPath, true);
}
catch { }
try
{
if (Directory.Exists(LogsPath)) Directory.Delete(LogsPath, true);
}
catch { }
try
{
if (Directory.Exists(SteamAppsPath)) Directory.Delete(SteamAppsPath, true); // this is just a useless folder created from +app_update 4
} }
catch { } catch { }
}); });
@ -247,11 +216,8 @@ internal static class SteamCMD
if (type is null || int.TryParse(buildid, out int gamebuildId) && gamebuildId < buildId) if (type is null || int.TryParse(buildid, out int gamebuildId) && gamebuildId < buildId)
{ {
List<string> dlcAppIds = await ParseDlcAppIds(appInfo); List<string> dlcAppIds = await ParseDlcAppIds(appInfo);
foreach (string id in dlcAppIds) foreach (string dlcAppUpdateFile in dlcAppIds.Select(id => $@"{AppInfoPath}\{id}.vdf"))
{
string dlcAppUpdateFile = $@"{AppInfoPath}\{id}.vdf";
if (File.Exists(dlcAppUpdateFile)) File.Delete(dlcAppUpdateFile); if (File.Exists(dlcAppUpdateFile)) File.Delete(dlcAppUpdateFile);
}
if (File.Exists(appUpdateFile)) File.Delete(appUpdateFile); if (File.Exists(appUpdateFile)) File.Delete(appUpdateFile);
goto restart; goto restart;
} }
@ -267,18 +233,15 @@ internal static class SteamCMD
#pragma warning restore IDE0150 // Prefer 'null' check over type check #pragma warning restore IDE0150 // Prefer 'null' check over type check
VToken extended = appInfo.Value.GetChild("extended"); VToken extended = appInfo.Value.GetChild("extended");
if (extended is not null) if (extended is not null)
foreach (VProperty property in extended) foreach (VProperty property in extended.Where(p => p is VProperty && (p as VProperty).Key == "listofdlc"))
if (property.Key == "listofdlc") foreach (string id in property.Value.ToString().Split(","))
foreach (string id in property.Value.ToString().Split(",")) if (int.TryParse(id, out int appId) && !dlcIds.Contains("" + appId))
if (int.TryParse(id, out int appId) dlcIds.Add("" + appId);
&& !dlcIds.Contains("" + appId))
dlcIds.Add("" + appId);
VToken depots = appInfo.Value.GetChild("depots"); VToken depots = appInfo.Value.GetChild("depots");
if (depots is not null) foreach (VProperty property in depots) if (depots is not null)
if (int.TryParse(property.Key, out int _) foreach (VProperty property in depots.Where(p => p is VProperty && int.TryParse((p as VProperty).Key, out int _)))
&& int.TryParse(property.Value.GetChild("dlcappid")?.ToString(), out int appid) if (int.TryParse(property.Value.GetChild("dlcappid")?.ToString(), out int appId) && !dlcIds.Contains("" + appId))
&& !dlcIds.Contains("" + appid)) dlcIds.Add("" + appId);
dlcIds.Add("" + appid);
return dlcIds; return dlcIds;
}); });

View file

@ -34,9 +34,9 @@ internal static class SteamLibrary
Thread.Sleep(0); Thread.Sleep(0);
List<(string appId, string name, string branch, int buildId, string gameDirectory)> directoryGames = await GetGamesFromLibraryDirectory(libraryDirectory); List<(string appId, string name, string branch, int buildId, string gameDirectory)> directoryGames = await GetGamesFromLibraryDirectory(libraryDirectory);
if (directoryGames is not null) if (directoryGames is not null)
foreach ((string appId, string name, string branch, int buildId, string gameDirectory) game in directoryGames) foreach ((string appId, string name, string branch, int buildId, string gameDirectory) game in directoryGames
if (!games.Any(_game => _game.appId == game.appId)) .Where(game => !games.Any(_game => _game.appId == game.appId)))
games.Add(game); games.Add(game);
} }
return games; return games;
}); });
@ -111,14 +111,13 @@ internal static class SteamLibrary
gameDirectories.Add(libraryFolder); gameDirectories.Add(libraryFolder);
string libraryFolders = libraryFolder + @"\libraryfolders.vdf"; string libraryFolders = libraryFolder + @"\libraryfolders.vdf";
if (File.Exists(libraryFolders) && ValveDataFile.TryDeserialize(File.ReadAllText(libraryFolders, Encoding.UTF8), out VProperty result)) if (File.Exists(libraryFolders) && ValveDataFile.TryDeserialize(File.ReadAllText(libraryFolders, Encoding.UTF8), out VProperty result))
foreach (VProperty property in result.Value) foreach (VProperty property in result.Value.Where(p => p is VProperty && int.TryParse((p as VProperty).Key, out int _)))
if (int.TryParse(property.Key, out int _)) {
{ string path = property.Value.GetChild("path")?.ToString();
string path = property.Value.GetChild("path")?.ToString(); if (string.IsNullOrWhiteSpace(path)) continue;
if (string.IsNullOrWhiteSpace(path)) continue; path += @"\steamapps";
path += @"\steamapps"; if (Directory.Exists(path) && !gameDirectories.Contains(path)) gameDirectories.Add(path);
if (Directory.Exists(path) && !gameDirectories.Contains(path)) gameDirectories.Add(path); }
}
} }
} }
return gameDirectories; return gameDirectories;

View file

@ -35,31 +35,32 @@ internal static class SteamStore
if (response is not null) if (response is not null)
{ {
IDictionary<string, JToken> apps = JsonConvert.DeserializeObject(response) as dynamic; IDictionary<string, JToken> apps = JsonConvert.DeserializeObject(response) as dynamic;
foreach (KeyValuePair<string, JToken> app in apps) if (apps is not null)
{ foreach (KeyValuePair<string, JToken> app in apps)
try
{ {
AppData data = JsonConvert.DeserializeObject<AppDetails>(app.Value.ToString()).data; try
if (data is not null)
{ {
try AppData data = JsonConvert.DeserializeObject<AppDetails>(app.Value.ToString()).data;
if (data is not null)
{ {
File.WriteAllText(cacheFile, JsonConvert.SerializeObject(data, Formatting.Indented)); try
{
File.WriteAllText(cacheFile, JsonConvert.SerializeObject(data, Formatting.Indented));
}
catch //(Exception e)
{
//using DialogForm dialogForm = new(null);
//dialogForm.Show(SystemIcons.Error, "Unsuccessful serialization of query for appid " + appId + ":\n\n" + e.ToString(), "FUCK");
}
return data;
} }
catch //(Exception e) }
{ catch //(Exception e)
//using DialogForm dialogForm = new(null); {
//dialogForm.Show(SystemIcons.Error, "Unsuccessful serialization of query for appid " + appId + ":\n\n" + e.ToString(), "FUCK"); //using DialogForm dialogForm = new(null);
} //dialogForm.Show(SystemIcons.Error, "Unsuccessful deserialization of query for appid " + appId + ":\n\n" + e.ToString(), "FUCK");
return data;
} }
} }
catch //(Exception e)
{
//using DialogForm dialogForm = new(null);
//dialogForm.Show(SystemIcons.Error, "Unsuccessful deserialization of query for appid " + appId + ":\n\n" + e.ToString(), "FUCK");
}
}
} }
} }
if (cachedExists) if (cachedExists)

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
namespace CreamInstaller.Utility; namespace CreamInstaller.Utility;
@ -10,11 +11,11 @@ internal static class ExceptionHandler
{ {
while (e.InnerException is not null) // we usually don't need the outer exceptions while (e.InnerException is not null) // we usually don't need the outer exceptions
e = e.InnerException; e = e.InnerException;
string output = ""; StringBuilder output = new();
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 += "STACK TRACE\n"; output.Append("STACK TRACE\n");
for (int i = 0; i < Math.Min(stackTrace.Length, 3); i++) for (int i = 0; i < Math.Min(stackTrace.Length, 3); i++)
{ {
string line = stackTrace[i]; string line = stackTrace[i];
@ -23,31 +24,31 @@ internal static class ExceptionHandler
int ciNum = line.LastIndexOf(@"CreamInstaller\"); int ciNum = line.LastIndexOf(@"CreamInstaller\");
int lineNum = line.LastIndexOf(":line "); int lineNum = line.LastIndexOf(":line ");
if (line is not null && atNum != -1) if (line is not null && atNum != -1)
output += "\n " + (inNum != -1 ? line[atNum..(inNum - 1)] : line[atNum..]) output.Append("\n " + (inNum != -1 ? line[atNum..(inNum - 1)] : line[atNum..])
+ (inNum != -1 ? ("\n " + (inNum != -1 ? ("\n "
+ (ciNum != -1 ? ("in " + (ciNum != -1 ? ("in "
+ (lineNum != -1 ? line[ciNum..lineNum] + (lineNum != -1 ? line[ciNum..lineNum]
+ "\n on " + line[(lineNum + 1)..] + "\n on " + line[(lineNum + 1)..]
: line[ciNum..])) : line[ciNum..]))
: line[inNum..])) : line[inNum..]))
: null); : null));
} }
} }
string[] messageLines = e.Message?.Split('\n'); string[] messageLines = e.Message?.Split('\n');
if (messageLines is not null && messageLines.Length > 0) if (messageLines is not null && messageLines.Length > 0)
{ {
if (output.Length > 0) if (output.Length > 0)
output += "\n\n"; output.Append("\n\n");
output += "MESSAGE\n"; output.Append("MESSAGE\n");
for (int i = 0; i < messageLines.Length; i++) for (int i = 0; i < messageLines.Length; i++)
{ {
string line = messageLines[i]; string line = messageLines[i];
if (line is not null) if (line is not null)
output += "\n " + line; output.Append("\n " + line);
} }
} }
using DialogForm dialogForm = new(form ?? Form.ActiveForm); using DialogForm dialogForm = new(form ?? Form.ActiveForm);
return dialogForm.Show(SystemIcons.Error, output, acceptButtonText, cancelButtonText, customFormText: caption) == DialogResult.OK; return dialogForm.Show(SystemIcons.Error, output.ToString(), acceptButtonText, cancelButtonText, customFormText: caption) == DialogResult.OK;
} }
internal static void HandleFatalException(this Exception e) internal static void HandleFatalException(this Exception e)