- 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 Graphics graphics = Graphics.FromImage(bitmap);
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
ImageCodecInfo jpeg = ImageCodecInfo.GetImageEncoders()[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));
Clipboard.SetImage(bitmap);
e.Handled = true;

View file

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

View file

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

View file

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

View file

@ -18,7 +18,7 @@ namespace CreamInstaller;
internal partial class InstallForm : CustomForm
{
internal bool Reselecting;
internal bool Uninstalling;
internal readonly bool Uninstalling;
internal InstallForm(IWin32Window owner, bool uninstall = false) : base(owner)
{
@ -36,7 +36,7 @@ internal partial class InstallForm : CustomForm
if (!userProgressBar.Disposing && !userProgressBar.IsDisposed)
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;
userProgressBar.Value = value;
});
@ -374,7 +374,7 @@ internal partial class InstallForm : CustomForm
}
catch (Exception exception)
{
UpdateUser($"Operation failed for {selection.Name}: " + exception.ToString(), InstallationLog.Error);
UpdateUser($"Operation failed for {selection.Name}: " + exception, InstallationLog.Error);
}
++CompleteOperationsCount;
}
@ -403,7 +403,7 @@ internal partial class InstallForm : CustomForm
}
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;
}
userProgressBar.Value = userProgressBar.Maximum;

View file

@ -13,19 +13,6 @@ namespace CreamInstaller
/// </summary>
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
/// <summary>
@ -109,7 +96,6 @@ namespace CreamInstaller
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "MainForm";
this.TopMost = true;
this.Load += new System.EventHandler(this.OnLoad);
this.ResumeLayout(false);

View file

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
@ -26,7 +27,7 @@ internal partial class MainForm : CustomForm
Text = Program.ApplicationNameShort;
}
private static CancellationTokenSource cancellationTokenSource;
private CancellationTokenSource cancellationTokenSource;
private void StartProgram()
{
@ -42,9 +43,9 @@ internal partial class MainForm : CustomForm
Close();
}
private static UpdateManager updateManager;
private static Version latestVersion;
private static IReadOnlyList<Version> versions;
private UpdateManager updateManager;
private Version latestVersion;
private IReadOnlyList<Version> versions;
private async void OnLoad()
{
@ -93,32 +94,31 @@ internal partial class MainForm : CustomForm
updateButton.Click += new(OnUpdate);
changelogTreeView.Visible = true;
Version currentVersion = new(Application.ProductVersion);
foreach (Version version in versions)
if (version > currentVersion && !changelogTreeView.Nodes.ContainsKey(version.ToString()))
foreach (Version version in versions.Where(v => v > currentVersion && !changelogTreeView.Nodes.ContainsKey(v.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}");
root.Name = root.Text;
changelogTreeView.Nodes.Add(root);
if (changelogTreeView.Nodes.Count > 0) changelogTreeView.Nodes[0].EnsureVisible();
_ = Task.Run(async () =>
{
HtmlNodeCollection nodes = await HttpClientManager.GetDocumentNodes(
$"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)
HtmlNodeCollection nodes = await HttpClientManager.GetDocumentNodes(
$"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
{
Program.Invoke(changelogTreeView, delegate
{
TreeNode change = new();
change.Text = HttpUtility.HtmlDecode(node.InnerText);
root.Nodes.Add(change);
root.Expand();
if (changelogTreeView.Nodes.Count > 0) changelogTreeView.Nodes[0].EnsureVisible();
});
}
});
}
TreeNode change = new();
change.Text = HttpUtility.HtmlDecode(node.InnerText);
root.Nodes.Add(change);
root.Expand();
if (changelogTreeView.Nodes.Count > 0) changelogTreeView.Nodes[0].EnsureVisible();
});
}
});
}
}
}
@ -193,4 +193,13 @@ internal partial class MainForm : CustomForm
updateManager.Dispose();
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.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "SelectDialogForm";
this.TopMost = true;
this.groupBox.ResumeLayout(false);
this.groupBox.PerformLayout();
this.flowLayoutPanel2.ResumeLayout(false);

View file

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

View file

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

View file

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
@ -226,8 +227,8 @@ internal partial class SelectForm : CustomForm
selection.DllDirectories = dllDirectories;
selection.IsSteam = true;
selection.ProductUrl = "https://store.steampowered.com/app/" + appId;
selection.IconUrl = IconGrabber.SteamAppImagesPath + @$"\{appId}\{appInfo?.Value?.GetChild("common")?.GetChild("icon")?.ToString()}.jpg";
selection.SubIconUrl = appData?.header_image ?? IconGrabber.SteamAppImagesPath + @$"\{appId}\{appInfo?.Value?.GetChild("common")?.GetChild("clienticon")?.ToString()}.ico";
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")}.ico";
selection.Publisher = appData?.publishers[0] ?? appInfo?.Value?.GetChild("extended")?.GetChild("publisher")?.ToString();
if (Program.Canceled) return;
@ -421,9 +422,8 @@ internal partial class SelectForm : CustomForm
if (!Program.IsGameBlocked(name, gameDirectory))
gameChoices.Add(("Steam", appId, name, ProgramsToScan is not null && ProgramsToScan.Any(p => p.id == appId)));
if (Directory.Exists(EpicLibrary.EpicManifestsPath))
foreach (Manifest manifest in await EpicLibrary.GetGames())
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)));
foreach (Manifest manifest in (await EpicLibrary.GetGames()).Where(m => !Program.IsGameBlocked(m.DisplayName, m.InstallLocation)))
gameChoices.Add(("Epic", manifest.CatalogNamespace, manifest.DisplayName, ProgramsToScan is not null && ProgramsToScan.Any(p => p.id == manifest.CatalogNamespace)));
if (gameChoices.Any())
{
using SelectDialogForm form = new(this);
@ -455,7 +455,7 @@ internal partial class SelectForm : CustomForm
Thread.Sleep(0);
if (_progress < 0 || _progress > maxProgress) maxProgress = -_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}%"
: $"Gathering and caching your applicable games and their DLCs . . . {p}%";
progressBar.Value = p;
@ -598,7 +598,8 @@ internal partial class SelectForm : CustomForm
(string gameAppId, (DlcType type, string name, string icon) app)? dlc = null;
if (selection is null) dlc = ProgramSelection.GetDlcFromId(id);
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)
return;
ContextMenuItem header = null;
@ -606,7 +607,7 @@ internal partial class SelectForm : CustomForm
header = new(node.Text, "Paradox Launcher");
else if (selection is not null)
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));
contextMenuStrip.Items.Add(header ?? new ContextMenuItem(node.Text));
string appInfoVDF = $@"{SteamCMD.AppInfoPath}\{id}.vdf";
@ -783,15 +784,15 @@ internal partial class SelectForm : CustomForm
private readonly string helpButtonListPrefix = "\n • ";
private void OnBlockProtectedGamesHelpButtonClicked(object sender, EventArgs e)
{
string blockedGames = "";
StringBuilder blockedGames = new();
foreach (string name in Program.ProtectedGames)
blockedGames += helpButtonListPrefix + name;
string blockedDirectories = "";
blockedGames.Append(helpButtonListPrefix + name);
StringBuilder blockedDirectories = new();
foreach (string path in Program.ProtectedGameDirectories)
blockedDirectories += helpButtonListPrefix + path;
string blockedDirectoryExceptions = "";
blockedDirectories.Append(helpButtonListPrefix + path);
StringBuilder blockedDirectoryExceptions = new();
foreach (string name in Program.ProtectedGameDirectoryExceptions)
blockedDirectoryExceptions += helpButtonListPrefix + name;
blockedDirectoryExceptions.Append(helpButtonListPrefix + name);
using DialogForm form = new(this);
form.Show(SystemIcons.Information,
"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)
{
paradoxLauncher.ExtraDlc.Clear();
foreach (ProgramSelection selection in ProgramSelection.AllEnabled)
{
if (selection == paradoxLauncher || selection.Publisher != "Paradox Interactive") continue;
foreach (ProgramSelection selection in ProgramSelection.AllEnabled.Where(s => s != paradoxLauncher && s.Publisher == "Paradox Interactive"))
paradoxLauncher.ExtraDlc.Add(new(selection.Id, selection.Name, selection.SelectedDlc));
}
if (!paradoxLauncher.ExtraDlc.Any())
foreach (ProgramSelection selection in ProgramSelection.AllSafe)
{
if (selection == paradoxLauncher || selection.Publisher != "Paradox Interactive") continue;
foreach (ProgramSelection selection in ProgramSelection.AllSafe.Where(s => s != paradoxLauncher && s.Publisher == "Paradox Interactive"))
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 List<ProgramSelection> All = new();
internal static readonly List<ProgramSelection> All = new();
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)
{
foreach (ProgramSelection selection in AllSafe)
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in selection.AllDlc)
if (pair.Key == dlcId) return (selection.Id, pair.Value);
foreach (KeyValuePair<string, (DlcType type, string name, string icon)> pair in selection.AllDlc.Where(p => p.Key == dlcId))
return (selection.Id, pair.Value);
return null;
}
}

View file

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

View file

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

View file

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

View file

@ -1,5 +1,6 @@
using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
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
e = e.InnerException;
string output = "";
StringBuilder output = new();
string[] stackTrace = e.StackTrace?.Split('\n');
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++)
{
string line = stackTrace[i];
@ -23,31 +24,31 @@ internal static class ExceptionHandler
int ciNum = line.LastIndexOf(@"CreamInstaller\");
int lineNum = line.LastIndexOf(":line ");
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 "
+ (ciNum != -1 ? ("in "
+ (lineNum != -1 ? line[ciNum..lineNum]
+ "\n on " + line[(lineNum + 1)..]
: line[ciNum..]))
: line[inNum..]))
: null);
: null));
}
}
string[] messageLines = e.Message?.Split('\n');
if (messageLines is not null && messageLines.Length > 0)
{
if (output.Length > 0)
output += "\n\n";
output += "MESSAGE\n";
output.Append("\n\n");
output.Append("MESSAGE\n");
for (int i = 0; i < messageLines.Length; i++)
{
string line = messageLines[i];
if (line is not null)
output += "\n " + line;
output.Append("\n " + line);
}
}
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)