From 3e50f5fa70c0daf651ba9e4da5666fb84087a1bd Mon Sep 17 00:00:00 2001 From: pointfeev Date: Fri, 5 Nov 2021 01:42:25 -0400 Subject: [PATCH] appinfo gathering, caching, and basic display --- CreamInstaller/CreamInstaller.csproj | 120 ++++++------ CreamInstaller/InstallForm.cs | 18 +- CreamInstaller/ProgramSelection.cs | 17 +- CreamInstaller/SelectForm.Designer.cs | 60 +++--- CreamInstaller/SelectForm.cs | 252 ++++++++++++++++---------- CreamInstaller/SteamCMD.cs | 60 ++++-- 6 files changed, 294 insertions(+), 233 deletions(-) diff --git a/CreamInstaller/CreamInstaller.csproj b/CreamInstaller/CreamInstaller.csproj index c6c8a23..7b44ed8 100644 --- a/CreamInstaller/CreamInstaller.csproj +++ b/CreamInstaller/CreamInstaller.csproj @@ -1,69 +1,67 @@  - - WinExe - net5.0-windows - true - ini.ico - true - 2.0.0.0 - ini.ico - - Automatically downloads and installs CreamAPI files for programs/games. - LICENSE - 2021, pointfeev (https://github.com/pointfeev) - true - https://github.com/pointfeev/CreamInstaller - https://github.com/pointfeev/CreamInstaller - git - Automatically downloads and installs CreamAPI files for programs/games. - steam, dlc - CreamInstaller - CreamInstaller - CreamAPI Downloader & Installer - pointfeev - pointfeev.creaminstaller - CreamInstaller.Program - + + WinExe + net5.0-windows + true + ini.ico + true + 2.0.0.0 + ini.ico + + Automatically downloads and installs CreamAPI files for programs/games. + LICENSE + 2021, pointfeev (https://github.com/pointfeev) + true + https://github.com/pointfeev/CreamInstaller + https://github.com/pointfeev/CreamInstaller + git + Automatically downloads and installs CreamAPI files for programs/games. + steam, dlc + CreamInstaller + CreamInstaller + CreamAPI Downloader & Installer + pointfeev + pointfeev.creaminstaller + CreamInstaller.Program + - - embedded - true - TRACE - + + embedded + true + TRACE + - - - - - + + + + - - - - - True - True - Resources.resx - - + + + + + True + True + Resources.resx + + - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - - True - - - - True - - - + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + True + + + + True + + + \ No newline at end of file diff --git a/CreamInstaller/InstallForm.cs b/CreamInstaller/InstallForm.cs index 01b08f5..823fd6e 100644 --- a/CreamInstaller/InstallForm.cs +++ b/CreamInstaller/InstallForm.cs @@ -147,18 +147,13 @@ namespace CreamInstaller private void Operate() { - OperationsCount = Program.ProgramSelections.FindAll(selection => selection.Enabled).Count; + OperationsCount = Program.ProgramSelections.ToList().FindAll(selection => selection.Enabled).Count; CompleteOperationsCount = 0; foreach (ProgramSelection selection in Program.ProgramSelections.ToList()) { - if (!selection.Enabled) { continue; } - - if (!Program.IsProgramRunningDialog(this, selection)) - { - throw new OperationCanceledException(); - } - + if (!selection.Enabled) continue; + if (!Program.IsProgramRunningDialog(this, selection)) throw new OperationCanceledException(); try { OperateFor(selection); @@ -169,13 +164,10 @@ namespace CreamInstaller { UpdateUser($"Operation failed for {selection.DisplayName}: " + exception.ToString(), LogColor.Error); } - ++CompleteOperationsCount; } - Program.Cleanup(); - - List FailedSelections = Program.ProgramSelections.FindAll(selection => selection.Enabled); + List FailedSelections = Program.ProgramSelections.ToList().FindAll(selection => selection.Enabled); if (FailedSelections.Any()) { if (FailedSelections.Count == 1) @@ -189,7 +181,7 @@ namespace CreamInstaller } } - private readonly int ProgramCount = Program.ProgramSelections.FindAll(selection => selection.Enabled).Count; + private readonly int ProgramCount = Program.ProgramSelections.ToList().FindAll(selection => selection.Enabled).Count; private void Start() { diff --git a/CreamInstaller/ProgramSelection.cs b/CreamInstaller/ProgramSelection.cs index 5148fc6..58f328a 100644 --- a/CreamInstaller/ProgramSelection.cs +++ b/CreamInstaller/ProgramSelection.cs @@ -6,7 +6,7 @@ namespace CreamInstaller { public bool Enabled = true; - public string Name; + public string Identifier; public string DisplayName; public string RootDirectory; public int SteamAppId; @@ -19,23 +19,14 @@ namespace CreamInstaller foreach (string directory in SteamApiDllDirectories) { string file = directory + "\\steam_api64.dll"; - if (file.IsFilePathLocked()) - { - return true; - } + if (file.IsFilePathLocked()) return true; } return false; } } - public ProgramSelection() - { - Program.ProgramSelections.Add(this); - } + public ProgramSelection() => Program.ProgramSelections.Add(this); - public void Toggle(bool Enabled) - { - this.Enabled = Enabled; - } + public void Toggle(bool Enabled) => this.Enabled = Enabled; } } \ No newline at end of file diff --git a/CreamInstaller/SelectForm.Designer.cs b/CreamInstaller/SelectForm.Designer.cs index b2b9e78..0d41770 100644 --- a/CreamInstaller/SelectForm.Designer.cs +++ b/CreamInstaller/SelectForm.Designer.cs @@ -1,5 +1,4 @@  -using System; using System.Windows.Forms; namespace CreamInstaller @@ -37,9 +36,9 @@ namespace CreamInstaller this.cancelButton = new System.Windows.Forms.Button(); this.label1 = new System.Windows.Forms.Label(); this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.allCheckBox = new System.Windows.Forms.CheckBox(); this.noneFoundLabel = new System.Windows.Forms.Label(); - this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); + this.treeView1 = new System.Windows.Forms.TreeView(); + this.allCheckBox = new System.Windows.Forms.CheckBox(); this.progressBar1 = new System.Windows.Forms.ProgressBar(); this.label2 = new System.Windows.Forms.Label(); this.scanButton = new System.Windows.Forms.Button(); @@ -81,9 +80,9 @@ namespace CreamInstaller this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.groupBox1.Controls.Add(this.allCheckBox); this.groupBox1.Controls.Add(this.noneFoundLabel); - this.groupBox1.Controls.Add(this.flowLayoutPanel1); + this.groupBox1.Controls.Add(this.treeView1); + this.groupBox1.Controls.Add(this.allCheckBox); this.groupBox1.Location = new System.Drawing.Point(12, 12); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(460, 236); @@ -91,6 +90,32 @@ namespace CreamInstaller this.groupBox1.TabStop = false; this.groupBox1.Text = "Programs / Games"; // + // noneFoundLabel + // + this.noneFoundLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.noneFoundLabel.Location = new System.Drawing.Point(6, 22); + this.noneFoundLabel.Name = "noneFoundLabel"; + this.noneFoundLabel.Size = new System.Drawing.Size(448, 208); + this.noneFoundLabel.TabIndex = 1002; + this.noneFoundLabel.Text = "No CreamAPI-applicable programs were found on your computer!"; + this.noneFoundLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.noneFoundLabel.Visible = false; + // + // treeView1 + // + this.treeView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.treeView1.CheckBoxes = true; + this.treeView1.Location = new System.Drawing.Point(6, 22); + this.treeView1.Name = "treeView1"; + this.treeView1.ShowPlusMinus = false; + this.treeView1.ShowRootLines = false; + this.treeView1.Size = new System.Drawing.Size(448, 208); + this.treeView1.TabIndex = 1001; + // // allCheckBox // this.allCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); @@ -106,27 +131,6 @@ namespace CreamInstaller this.allCheckBox.UseVisualStyleBackColor = true; this.allCheckBox.CheckedChanged += new System.EventHandler(this.OnAllCheckBoxChanged); // - // noneFoundLabel - // - this.noneFoundLabel.Dock = System.Windows.Forms.DockStyle.Fill; - this.noneFoundLabel.Enabled = false; - this.noneFoundLabel.Location = new System.Drawing.Point(3, 19); - this.noneFoundLabel.Name = "noneFoundLabel"; - this.noneFoundLabel.Size = new System.Drawing.Size(454, 214); - this.noneFoundLabel.TabIndex = 0; - this.noneFoundLabel.Text = "No CreamAPI-applicable programs or games were found on your computer!"; - this.noneFoundLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; - this.noneFoundLabel.Visible = false; - // - // flowLayoutPanel1 - // - this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; - this.flowLayoutPanel1.Location = new System.Drawing.Point(3, 19); - this.flowLayoutPanel1.Name = "flowLayoutPanel1"; - this.flowLayoutPanel1.Size = new System.Drawing.Size(454, 214); - this.flowLayoutPanel1.TabIndex = 1000; - // // progressBar1 // this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) @@ -193,12 +197,12 @@ namespace CreamInstaller private System.Windows.Forms.Button cancelButton; private System.Windows.Forms.Label label1; private System.Windows.Forms.GroupBox groupBox1; - private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; private System.Windows.Forms.ProgressBar progressBar1; private System.Windows.Forms.Label label2; private System.Windows.Forms.CheckBox allCheckBox; - private Label noneFoundLabel; private Button scanButton; + private TreeView treeView1; + private Label noneFoundLabel; } } diff --git a/CreamInstaller/SelectForm.cs b/CreamInstaller/SelectForm.cs index 6d7c1e1..f027319 100644 --- a/CreamInstaller/SelectForm.cs +++ b/CreamInstaller/SelectForm.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Forms; @@ -48,7 +47,7 @@ namespace CreamInstaller { steamApiDllDirectories = new(); if (Program.Canceled) return false; - string api = "";//gameDirectory + "\\steam_api.dll"; + string api = gameDirectory + "\\steam_api.dll"; string api64 = gameDirectory + "\\steam_api64.dll"; if (File.Exists(api) || File.Exists(api64)) steamApiDllDirectories.Add(gameDirectory); foreach (string _directory in Directory.GetDirectories(gameDirectory)) @@ -92,15 +91,15 @@ namespace CreamInstaller return true; } - private readonly List checkBoxes = new(); + private readonly List treeNodes = new(); - private readonly Dictionary dlc = new(); + internal readonly Dictionary>> DLC = new(); - [DllImport("kernel32")] - private static extern bool AllocConsole(); + internal List RunningTasks = null; private void GetCreamApiApplicablePrograms(IProgress progress) { + int cur = 0; if (Program.Canceled) return; List> applicablePrograms = new(); string launcherRootDirectory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Programs\\Paradox Interactive"; @@ -109,85 +108,122 @@ namespace CreamInstaller if (GetGameDirectoriesFromLibraryDirectory(libraryDirectory, out List gameDirectories)) foreach (string gameDirectory in gameDirectories) applicablePrograms.Add(new Tuple(Path.GetFileName(gameDirectory) ?? "unknown_" + applicablePrograms.Count, gameDirectory)); - List tasks = new(); + RunningTasks = new(); foreach (Tuple program in applicablePrograms) { - string name = program.Item1; + string identifier = program.Item1; string rootDirectory = program.Item2; if (Program.Canceled) return; - Task task = new Task(() => + Task task = new(() => { - int steamAppId = 0; - if (Program.Canceled || Program.ProgramSelections.Any(s => s.Name == name) - || (name != "Paradox Launcher" && !GetSteamAppIdFromGameDirectory(rootDirectory, out steamAppId)) - || !GetSteamApiDllDirectoriesFromGameDirectory(rootDirectory, out List steamApiDllDirectories)) - return; - - Dictionary appInfo = null; - if (Program.Canceled || (name != "Paradox Launcher" && !SteamCMD.GetAppInfo(steamAppId, out appInfo))) return; - string list = null; - if (!(appInfo is null) && appInfo.TryGetValue("listofdlc", out list)) + try { + int steamAppId = 0; + if (Program.Canceled + || (identifier != "Paradox Launcher" && !GetSteamAppIdFromGameDirectory(rootDirectory, out steamAppId)) + || !GetSteamApiDllDirectoriesFromGameDirectory(rootDirectory, out List steamApiDllDirectories)) + return; + + Dictionary appInfo = null; + if (Program.Canceled || (identifier != "Paradox Launcher" && !SteamCMD.GetAppInfo(steamAppId, out appInfo))) return; + string list = null; + List> dlc = null; + if (!DLC.TryGetValue(steamAppId, out dlc)) + { + dlc = new(); + DLC.Add(steamAppId, dlc); + } if (Program.Canceled) return; - string[] nums = list.Split(","); - List ids = new(); - foreach (string s in nums) ids.Add(int.Parse(s)); - foreach (int id in ids) + List dlcTasks = new(); + if (!(appInfo is null) && appInfo.TryGetValue("listofdlc", out list)) { if (Program.Canceled) return; - string dlcName = null; - Dictionary dlcAppInfo = null; - //if (SteamCMD.GetAppInfo(id, out dlcAppInfo)) dlcAppInfo.TryGetValue("name", out dlcName); - dlc.Add(id, dlcName); - Console.WriteLine(id + " = " + dlcName); + Task task = new(() => + { + try + { + string[] nums = list.Split(","); + List ids = new(); + foreach (string s in nums) + { + if (Program.Canceled) return; + ids.Add(int.Parse(s)); + } + foreach (int id in ids) + { + if (Program.Canceled) return; + string dlcName = null; + Dictionary dlcAppInfo = null; + if (SteamCMD.GetAppInfo(id, out dlcAppInfo)) dlcAppInfo.TryGetValue("name", out dlcName); + if (Program.Canceled) return; + if (string.IsNullOrWhiteSpace(dlcName)) continue; + dlc.Add(new Tuple(id, dlcName)); + } + } + catch { } + }); + dlcTasks.Add(task); + RunningTasks.Add(task); + task.Start(); + progress.Report(-RunningTasks.Count); } - } - else if (name != "Paradox Launcher") return; + else if (identifier != "Paradox Launcher") return; + if (Program.Canceled) return; - ProgramSelection selection = new(); - selection.Name = name; - string displayName = name; - if (!(appInfo is null)) appInfo.TryGetValue("name", out displayName); - selection.DisplayName = displayName; - selection.RootDirectory = rootDirectory; - selection.SteamAppId = steamAppId; - selection.SteamApiDllDirectories = steamApiDllDirectories; + string displayName = identifier; + if (!(appInfo is null)) appInfo.TryGetValue("name", out displayName); + if (string.IsNullOrWhiteSpace(displayName)) return; + if (Program.Canceled) return; - flowLayoutPanel1.Invoke((MethodInvoker)delegate - { - CheckBox checkBox = new(); - checkBoxes.Add(checkBox); - checkBox.AutoSize = true; - checkBox.Parent = flowLayoutPanel1; - checkBox.Text = selection.DisplayName; - checkBox.Checked = true; - checkBox.Enabled = false; - checkBox.TabStop = true; - checkBox.TabIndex = 1 + checkBoxes.Count; + ProgramSelection selection = Program.ProgramSelections.Find(s => s.Identifier == identifier) ?? new(); + selection.Identifier = identifier; + selection.DisplayName = displayName; + selection.RootDirectory = rootDirectory; + selection.SteamAppId = steamAppId; + selection.SteamApiDllDirectories = steamApiDllDirectories; - checkBox.CheckedChanged += (sender, e) => + foreach (Task task in dlcTasks.ToList()) { - selection.Toggle(checkBox.Checked); - acceptButton.Enabled = Program.ProgramSelections.Any(selection => selection.Enabled); - allCheckBox.CheckedChanged -= OnAllCheckBoxChanged; - allCheckBox.Checked = checkBoxes.TrueForAll(checkBox => checkBox.Checked); - allCheckBox.CheckedChanged += OnAllCheckBoxChanged; - }; - }); + if (Program.Canceled) return; + progress.Report(cur++); + task.Wait(); + } + if (Program.Canceled) return; + treeView1.Invoke((MethodInvoker)delegate + { + if (Program.Canceled) return; + TreeNode programNode = treeNodes.Find(s => s.Text == displayName) ?? new(); + programNode.Text = displayName; + programNode.Remove(); + treeView1.Nodes.Add(programNode); + treeNodes.Remove(programNode); + treeNodes.Add(programNode); + foreach (Tuple dlcApp in dlc.ToList()) + { + if (Program.Canceled || programNode is null) return; + TreeNode dlcNode = treeNodes.Find(s => s.Text == dlcApp.Item2) ?? new(); + dlcNode.Text = dlcApp.Item2; + dlcNode.Remove(); + programNode.Nodes.Add(dlcNode); + treeNodes.Remove(dlcNode); + treeNodes.Add(dlcNode); + } + }); + } + catch { } }); - tasks.Add(task); + RunningTasks.Add(task); task.Start(); } - int max = tasks.Count; - progress.Report(max); - int cur = 0; + progress.Report(-RunningTasks.Count); progress.Report(cur); - foreach (Task task in tasks) + foreach (Task task in RunningTasks.ToList()) { + if (Program.Canceled) return; progress.Report(cur++); task.Wait(); } - progress.Report(max); + progress.Report(RunningTasks.Count); } private async void OnLoad() @@ -198,57 +234,52 @@ namespace CreamInstaller noneFoundLabel.Visible = false; allCheckBox.Enabled = false; acceptButton.Enabled = false; - checkBoxes.ForEach(checkBox => checkBox.Enabled = false); + treeView1.CheckBoxes = false; label2.Visible = true; progressBar1.Visible = true; progressBar1.Value = 0; groupBox1.Size = new Size(groupBox1.Size.Width, groupBox1.Size.Height - 44); - AllocConsole(); - bool setup = true; int maxProgress = 0; + int curProgress = 0; Progress progress = new(); IProgress iProgress = progress; progress.ProgressChanged += (sender, _progress) => { - if (maxProgress == 0) maxProgress = _progress; - else - { - int p = Math.Max(Math.Min((int)((float)(_progress / (float)maxProgress) * 100), 100), 0); - if (setup) label2.Text = "Setting up SteamCMD . . . " + p + "% (" + _progress + "/" + maxProgress + ")"; - else label2.Text = "Scanning for CreamAPI-applicable programs on your computer . . . " + p + "% (" + _progress + "/" + maxProgress + ")"; - progressBar1.Value = p; - } + if (_progress < 0) maxProgress = -_progress; + else curProgress = _progress; + int p = Math.Max(Math.Min((int)((float)(curProgress / (float)maxProgress) * 100), 100), 0); + if (setup) label2.Text = "Setting up SteamCMD . . . " + p + "%"; + else label2.Text = "Gathering your CreamAPI-applicable games and their DLCs . . . " + p + "%"; + progressBar1.Value = p; }; - int max = 1660; // not exact, number varies - iProgress.Report(max); + iProgress.Report(-1660); // not exact, number varies int cur = 0; iProgress.Report(cur); label2.Text = "Setting up SteamCMD . . . "; - FileSystemWatcher watcher = new FileSystemWatcher(SteamCMD.DirectoryPath); + if (!Directory.Exists(SteamCMD.DirectoryPath)) Directory.CreateDirectory(SteamCMD.DirectoryPath); + FileSystemWatcher watcher = new(SteamCMD.DirectoryPath); watcher.Changed += (sender, e) => iProgress.Report(++cur); watcher.Filter = "*"; watcher.IncludeSubdirectories = true; watcher.EnableRaisingEvents = true; await Task.Run(() => SteamCMD.Setup()); watcher.Dispose(); - Clipboard.SetText(cur.ToString()); - maxProgress = 0; setup = false; - label2.Text = "Scanning for CreamAPI-applicable programs on your computer . . . "; + label2.Text = "Gathering your CreamAPI-applicable games and their DLCs . . . "; await Task.Run(() => GetCreamApiApplicablePrograms(iProgress)); Program.ProgramSelections.ForEach(selection => selection.SteamApiDllDirectories.RemoveAll(directory => !Directory.Exists(directory))); Program.ProgramSelections.RemoveAll(selection => !Directory.Exists(selection.RootDirectory) || !selection.SteamApiDllDirectories.Any()); - foreach (CheckBox checkBox in checkBoxes) + foreach (TreeNode treeNode in treeNodes) { - if (!Program.ProgramSelections.Any(selection => selection.DisplayName == checkBox.Text)) + if (treeNode.Parent is null && !Program.ProgramSelections.Any(selection => selection.DisplayName == treeNode.Text)) { - checkBox.Dispose(); + treeNode.Remove(); } } @@ -260,7 +291,9 @@ namespace CreamInstaller if (Program.ProgramSelections.Any()) { allCheckBox.Enabled = true; - checkBoxes.ForEach(checkBox => checkBox.Enabled = true); + treeView1.CheckBoxes = true; + treeView1.ExpandAll(); + treeNodes.ForEach(node => node.Checked = true); if (Program.ProgramSelections.Any(selection => selection.Enabled)) { acceptButton.Enabled = true; @@ -275,8 +308,32 @@ namespace CreamInstaller scanButton.Enabled = true; } + private void OnChange(object sender, TreeViewEventArgs e) + { + ProgramSelection selection = Program.ProgramSelections.ToList().Find(selection => selection.DisplayName == e.Node.Text); + if (selection is null) + { + treeView1.AfterCheck -= OnChange; + e.Node.Parent.Checked = e.Node.Parent.Nodes.Cast().ToList().Any(treeNode => treeNode.Checked); + treeView1.AfterCheck += OnChange; + } + else + { + selection.Toggle(e.Node.Checked); + treeView1.AfterCheck -= OnChange; + e.Node.Nodes.Cast().ToList().ForEach(treeNode => treeNode.Checked = e.Node.Checked); + treeView1.AfterCheck += OnChange; + acceptButton.Enabled = Program.ProgramSelections.ToList().Any(selection => selection.Enabled); + allCheckBox.CheckedChanged -= OnAllCheckBoxChanged; + allCheckBox.Checked = treeNodes.TrueForAll(treeNode => treeNode.Checked); + allCheckBox.CheckedChanged += OnAllCheckBoxChanged; + } + } + private void OnLoad(object sender, EventArgs e) { + treeView1.BeforeCollapse += (sender, e) => e.Cancel = true; + treeView1.AfterCheck += OnChange; OnLoad(); } @@ -284,7 +341,7 @@ namespace CreamInstaller { if (Program.ProgramSelections.Count > 0) { - foreach (ProgramSelection selection in Program.ProgramSelections) + foreach (ProgramSelection selection in Program.ProgramSelections.ToList()) { if (!Program.IsProgramRunningDialog(this, selection)) { @@ -297,11 +354,11 @@ namespace CreamInstaller installForm.ShowDialog(); if (installForm.Reselecting) { - foreach (CheckBox checkBox in checkBoxes) - { - checkBox.Checked = !checkBox.Checked; - checkBox.Checked = !checkBox.Checked; // to fire CheckChanged - } + //foreach (TreeNode treeNode in treeNodes) + //{ + // treeNode.Checked = !treeNode.Checked; + // treeNode.Checked = !treeNode.Checked; // to fire checked event + //} int X = installForm.Location.X + installForm.Size.Width / 2 - Size.Width / 2; int Y = installForm.Location.Y + installForm.Size.Height / 2 - Size.Height / 2; Location = new Point(X, Y); @@ -327,17 +384,12 @@ namespace CreamInstaller private void OnAllCheckBoxChanged(object sender, EventArgs e) { bool shouldCheck = false; - foreach (CheckBox checkBox in checkBoxes) - { - if (!checkBox.Checked) - { + foreach (TreeNode treeNode in treeNodes) + if (treeNode.Parent is null && !treeNode.Checked) shouldCheck = true; - } - } - foreach (CheckBox checkBox in checkBoxes) - { - checkBox.Checked = shouldCheck; - } + foreach (TreeNode treeNode in treeNodes) + if (treeNode.Parent is null) + treeNode.Checked = shouldCheck; allCheckBox.Checked = shouldCheck; } } diff --git a/CreamInstaller/SteamCMD.cs b/CreamInstaller/SteamCMD.cs index 1d37e35..7598a1a 100644 --- a/CreamInstaller/SteamCMD.cs +++ b/CreamInstaller/SteamCMD.cs @@ -1,5 +1,4 @@ -using SteamCmdFluentApi; -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -11,43 +10,68 @@ namespace CreamInstaller public static class SteamCMD { public static string DirectoryPath = Path.GetTempPath() + "CreamInstaller"; - public static string FilePath = DirectoryPath + "\\steamcmd.exe"; - public static string ArchivePath = DirectoryPath + "\\steamcmd.zip"; - public static string DllPath = DirectoryPath + "\\steamclient.dll"; + public static string FilePath = DirectoryPath + @"\steamcmd.exe"; + public static string ArchivePath = DirectoryPath + @"\steamcmd.zip"; + public static string DllPath = DirectoryPath + @"\steamclient.dll"; + public static string AppUpdatePath = DirectoryPath + @"\appupdate"; - private static SteamCmd current = null; - - public static SteamCmd Current + public static bool Run(string command, out string output) { - get + bool success = true; + List logs = new(); + ProcessStartInfo processStartInfo = new() { - if (current is null) current = SteamCmd.WithExecutable(FilePath); - return current; + FileName = FilePath, + RedirectStandardOutput = true, + RedirectStandardInput = true, + RedirectStandardError = true, + UseShellExecute = false, + Arguments = command, + CreateNoWindow = true + }; + using (Process process = Process.Start(processStartInfo)) + { + process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => logs.Add(e.Data); + process.BeginOutputReadLine(); + process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) => logs.Add(e.Data); + process.BeginErrorReadLine(); + process.WaitForExit(); } + output = string.Join("\r\n", logs); + return success; } public static void Setup() { Kill(); - if (!Directory.Exists(DirectoryPath)) Directory.CreateDirectory(DirectoryPath); if (!File.Exists(FilePath)) { - using (WebClient webClient = new WebClient()) webClient.DownloadFile("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip", ArchivePath); + using (WebClient webClient = new()) webClient.DownloadFile("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip", ArchivePath); ZipFile.ExtractToDirectory(ArchivePath, DirectoryPath); File.Delete(ArchivePath); } - if (!File.Exists(DllPath)) Current.TryToExecuteCommand($@"+login anonymous +app_info_update 1 +quit", out _); + if (!File.Exists(DllPath)) Run($@"+quit", out _); } public static bool GetAppInfo(int steamAppId, out Dictionary appInfo) { appInfo = new(); if (Program.Canceled) return false; - // need to find a way to request app info, currently it won't work from the command line like below - bool success = Current.TryToExecuteCommand($@"+login anonymous +app_info_update 1 +app_info_request {steamAppId} +app_info_print {steamAppId} +quit", out string output); - if (!success) return false; + string output = null; + string appUpdatePath = $@"{AppUpdatePath}\{steamAppId}"; + string appUpdateFile = $@"{appUpdatePath}\appinfo.txt"; + if (Directory.Exists(appUpdatePath) && File.Exists(appUpdateFile)) output = File.ReadAllText(appUpdateFile); + else + { + Run($@"+@ShutdownOnFailedCommand 0 +login anonymous +app_info_print {steamAppId} +force_install_dir {appUpdatePath} +app_update 4 +quit", out _); + if (Program.Canceled) return false; + Run($@"+@ShutdownOnFailedCommand 0 +login anonymous +app_info_print {steamAppId} +quit", out output); + File.WriteAllText(appUpdateFile, output); + } + if (Program.Canceled || output is null) return false; foreach (string s in output.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)) { + if (Program.Canceled) return false; int first = s.IndexOf("\""); int second = 1 + first + s.Substring(first + 1).IndexOf("\""); int third = 1 + second + s.Substring(second + 1).IndexOf("\""); @@ -65,7 +89,7 @@ namespace CreamInstaller public static void Kill() { - foreach (Process process in Process.GetProcessesByName("steamcmd")) { process.Kill(); process.WaitForExit(); } + foreach (Process process in Process.GetProcessesByName("steamcmd")) process.Kill(); } public static void Dispose()