From f5ba69f38091b1348a3f427eb75490b078494000 Mon Sep 17 00:00:00 2001 From: pointfeev Date: Fri, 29 Oct 2021 04:20:27 -0400 Subject: [PATCH] initial framework for v2.0 --- CreamInstaller/CreamInstaller.csproj | 4 +- CreamInstaller/InstallForm.cs | 70 ++--- CreamInstaller/MainForm.cs | 28 +- CreamInstaller/Program.cs | 79 +---- CreamInstaller/ProgramSelection.cs | 10 +- CreamInstaller/Properties/launchSettings.json | 2 +- CreamInstaller/SelectForm.cs | 297 +++++++++--------- CreamInstaller/SteamCMD.cs | 77 +++++ 8 files changed, 271 insertions(+), 296 deletions(-) create mode 100644 CreamInstaller/SteamCMD.cs diff --git a/CreamInstaller/CreamInstaller.csproj b/CreamInstaller/CreamInstaller.csproj index b3cd9af..c6c8a23 100644 --- a/CreamInstaller/CreamInstaller.csproj +++ b/CreamInstaller/CreamInstaller.csproj @@ -6,7 +6,7 @@ true ini.ico true - 1.0.6.4 + 2.0.0.0 ini.ico Automatically downloads and installs CreamAPI files for programs/games. @@ -34,7 +34,7 @@ - + diff --git a/CreamInstaller/InstallForm.cs b/CreamInstaller/InstallForm.cs index 2417494..01b08f5 100644 --- a/CreamInstaller/InstallForm.cs +++ b/CreamInstaller/InstallForm.cs @@ -4,8 +4,6 @@ using System.Drawing; using System.IO; using System.IO.Compression; using System.Linq; -using System.Threading; -using System.Threading.Tasks; using System.Windows.Forms; namespace CreamInstaller @@ -47,33 +45,10 @@ namespace CreamInstaller } } - private async Task OperateFor(ProgramSelection selection) + private void OperateFor(ProgramSelection selection) { UpdateProgress(0); - UpdateUser("Downloading CreamAPI files for " + selection.ProgramName + " . . . ", LogColor.Operation); - Program.OutputFile = selection.ProgramDirectory + "\\" + selection.DownloadNode.Name; - if (File.Exists(Program.OutputFile)) - { - try - { - File.Delete(Program.OutputFile); - } - catch - { - throw new CustomMessageException($"Unable to delete old archive file: {Program.OutputFile}"); - } - } - Progress progress = new Progress(delegate (double progress) - { - if (!Program.Canceled) - { - UpdateUser($"Downloading CreamAPI files for {selection.ProgramName} . . . {(int)progress}%", LogColor.Operation, log: false); - UpdateProgress((int)progress); - } - }); - Program.CancellationTokenSource = new CancellationTokenSource(); - Program.OutputTask = Program.MegaApiClient.DownloadFileAsync(selection.DownloadNode, Program.OutputFile, progress, Program.CancellationTokenSource.Token); - await Program.OutputTask; + UpdateUser("Downloading CreamAPI files for " + selection.DisplayName + " . . . ", LogColor.Operation); UpdateUser($"Downloaded archive: {Program.OutputFile}", LogColor.Resource); UpdateUser("Searching for CreamAPI files in downloaded archive . . . ", LogColor.Operation); string resourcePath = null; @@ -88,7 +63,7 @@ namespace CreamInstaller resourcePath = Path.GetDirectoryName(entry.FullName); UpdateUser("Got CreamAPI file path: " + resourcePath, LogColor.Resource); } - UpdateProgress((currentEntryCount / (Program.OutputArchive.Entries.Count * 2)) * 100); + UpdateProgress(currentEntryCount / (Program.OutputArchive.Entries.Count * 2) * 100); } foreach (ZipArchiveEntry entry in Program.OutputArchive.Entries) { @@ -98,7 +73,7 @@ namespace CreamInstaller resources.Add(entry); UpdateUser("Found CreamAPI file: " + entry.Name, LogColor.Resource); } - UpdateProgress((currentEntryCount / (Program.OutputArchive.Entries.Count * 2)) * 100); + UpdateProgress(currentEntryCount / (Program.OutputArchive.Entries.Count * 2) * 100); } if (resources.Count < 1) { @@ -108,7 +83,7 @@ namespace CreamInstaller { throw new OperationCanceledException(); } - UpdateUser("Installing CreamAPI files for " + selection.ProgramName + " . . . ", LogColor.Operation); + UpdateUser("Installing CreamAPI files for " + selection.DisplayName + " . . . ", LogColor.Operation); int currentFileCount = 0; foreach (string directory in selection.SteamApiDllDirectories) { @@ -155,7 +130,7 @@ namespace CreamInstaller throw new CustomMessageException($"Unable to overwrite Steam API file: {file}"); } UpdateUser("Installed file: " + file, LogColor.Resource); - UpdateProgress((currentFileCount / (resources.Count * selection.SteamApiDllDirectories.Count)) * 100); + UpdateProgress(currentFileCount / (resources.Count * selection.SteamApiDllDirectories.Count) * 100); } foreach (KeyValuePair keyValuePair in changesToRevert) { @@ -170,22 +145,15 @@ namespace CreamInstaller UpdateProgress(100); } - private async Task Operate() + private void Operate() { OperationsCount = Program.ProgramSelections.FindAll(selection => selection.Enabled).Count; CompleteOperationsCount = 0; foreach (ProgramSelection selection in Program.ProgramSelections.ToList()) { - if (Program.Canceled) - { - break; - } - if (!selection.Enabled) { continue; } - Program.Cleanup(cancel: false, logout: false); - if (!Program.IsProgramRunningDialog(this, selection)) { throw new OperationCanceledException(); @@ -193,27 +161,26 @@ namespace CreamInstaller try { - await OperateFor(selection); - - UpdateUser($"Operation succeeded for {selection.ProgramName}.", LogColor.Success); + OperateFor(selection); + UpdateUser($"Operation succeeded for {selection.DisplayName}.", LogColor.Success); selection.Toggle(false); } catch (Exception exception) { - UpdateUser($"Operation failed for {selection.ProgramName}: " + exception.ToString(), LogColor.Error); + UpdateUser($"Operation failed for {selection.DisplayName}: " + exception.ToString(), LogColor.Error); } ++CompleteOperationsCount; } - Program.Cleanup(logout: false); + Program.Cleanup(); List FailedSelections = Program.ProgramSelections.FindAll(selection => selection.Enabled); if (FailedSelections.Any()) { if (FailedSelections.Count == 1) { - throw new CustomMessageException($"Operation failed for {FailedSelections.First().ProgramName}."); + throw new CustomMessageException($"Operation failed for {FailedSelections.First().DisplayName}."); } else { @@ -224,9 +191,8 @@ namespace CreamInstaller private readonly int ProgramCount = Program.ProgramSelections.FindAll(selection => selection.Enabled).Count; - private async void Start() + private void Start() { - Program.Canceled = false; acceptButton.Enabled = false; retryButton.Enabled = false; cancelButton.Enabled = true; @@ -234,7 +200,7 @@ namespace CreamInstaller userProgressBar.Value = userProgressBar.Minimum; try { - await Operate(); + Operate(); UpdateUser("CreamAPI successfully downloaded and installed for " + ProgramCount + " program(s).", LogColor.Success); } catch (Exception exception) @@ -257,24 +223,24 @@ namespace CreamInstaller private void OnAccept(object sender, EventArgs e) { - Program.Cleanup(logout: false); + Program.Cleanup(); Close(); } private void OnRetry(object sender, EventArgs e) { - Program.Cleanup(logout: false); + Program.Cleanup(); Start(); } private void OnCancel(object sender, EventArgs e) { - Program.Cleanup(logout: false); + Program.Cleanup(); } private void OnReselect(object sender, EventArgs e) { - Program.Cleanup(logout: false); + Program.Cleanup(); Reselecting = true; Close(); } diff --git a/CreamInstaller/MainForm.cs b/CreamInstaller/MainForm.cs index 9190a1d..17d1ef7 100644 --- a/CreamInstaller/MainForm.cs +++ b/CreamInstaller/MainForm.cs @@ -1,5 +1,4 @@ -using CG.Web.MegaApiClient; -using Onova; +using Onova; using Onova.Models; using Onova.Services; using System; @@ -94,31 +93,6 @@ namespace CreamInstaller Environment.Exit(0); } } - - Program.MegaApiClient = new MegaApiClient(); - void Login() - { - try - { - Program.MegaApiClient.Login(); - } - catch (ApiException) - { - if (new DialogForm(this).Show(Program.ApplicationName, SystemIcons.Error, - $"ERROR: Failed logging into MEGA!" + - "\n\nMEGA is likely offline, please try again later . . .", - "Retry", "Cancel") == DialogResult.OK) - { - Login(); - } - else - { - Environment.Exit(0); - } - } - } - Login(); - OnLoad(); } diff --git a/CreamInstaller/Program.cs b/CreamInstaller/Program.cs index 43e0148..419461d 100644 --- a/CreamInstaller/Program.cs +++ b/CreamInstaller/Program.cs @@ -1,4 +1,3 @@ -using CG.Web.MegaApiClient; using System; using System.Collections.Generic; using System.Diagnostics; @@ -7,21 +6,18 @@ using System.IO; using System.IO.Compression; using System.Reflection; using System.Threading; -using System.Threading.Tasks; using System.Windows.Forms; namespace CreamInstaller { public static class Program { - public static string ApplicationName = "CreamInstaller v" + Application.ProductVersion + ": CreamAPI Downloader & Installer"; - - public static Assembly EntryAssembly = Assembly.GetEntryAssembly(); - public static Process CurrentProcess = Process.GetCurrentProcess(); - public static string CurrentProcessFilePath = CurrentProcess.MainModule.FileName; - public static string CurrentProcessDirectory = CurrentProcessFilePath.Substring(0, CurrentProcessFilePath.LastIndexOf("\\")); - - public static string BackupFileExtension = ".creaminstaller.backup"; + public static readonly string ApplicationName = "CreamInstaller v" + Application.ProductVersion + ": CreamAPI Downloader & Installer"; + 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"; [STAThread] private static void Main() @@ -43,7 +39,7 @@ namespace CreamInstaller if (selection.IsProgramRunning) { if (new DialogForm(form).Show(ApplicationName, SystemIcons.Error, - $"ERROR: {selection.ProgramName} is currently running!" + + $"ERROR: {selection.DisplayName} is currently running!" + "\n\nPlease close the program/game to continue . . . ", "Retry", "Cancel") == DialogResult.OK) { @@ -77,66 +73,15 @@ namespace CreamInstaller public static List ProgramSelections = new(); public static bool Canceled = false; - public static MegaApiClient MegaApiClient; - public static ZipArchive OutputArchive; - public static CancellationTokenSource CancellationTokenSource; - public static Task OutputTask; - public static string OutputFile; + public static string OutputFile = null; // placeholder, won't exist in new system + public static ZipArchive OutputArchive = null; // placeholder, won't exist in new system - public static void Cleanup(bool cancel = true, bool logout = true) + public static void Cleanup(bool cancel = true) { Canceled = cancel; - if (OutputArchive != null || CancellationTokenSource != null || OutputTask != null || OutputFile != null) - { - InstallForm?.UpdateUser("Cleaning up . . . ", LogColor.Cleanup); - } - if (OutputArchive != null) - { - OutputArchive.Dispose(); - OutputArchive = null; - } - if (CancellationTokenSource != null) - { - CancellationTokenSource.Cancel(); - } - if (OutputTask != null) - { - try - { - OutputTask.Wait(); - } - catch (AggregateException) { } - OutputTask.Dispose(); - OutputTask = null; - } - if (CancellationTokenSource != null) - { - CancellationTokenSource.Dispose(); - CancellationTokenSource = null; - } - if (OutputFile != null && File.Exists(OutputFile)) - { - try - { - File.Delete(OutputFile); - InstallForm?.UpdateUser($"Deleted archive: {OutputFile}", LogColor.Cleanup); - } - catch - { - InstallForm?.UpdateUser($"WARNING: Failed to clean up archive: {OutputFile}", LogColor.Warning); - } - OutputFile = null; - } - if (logout && MegaApiClient != null && MegaApiClient.IsLoggedIn) - { - InstallForm?.UpdateUser("Logging out of MEGA . . . ", LogColor.Cleanup); - MegaApiClient.Logout(); - } + SteamCMD.Kill(); } - private static void OnApplicationExit(object s, EventArgs e) - { - Cleanup(); - } + private static void OnApplicationExit(object s, EventArgs e) => Cleanup(); } } \ No newline at end of file diff --git a/CreamInstaller/ProgramSelection.cs b/CreamInstaller/ProgramSelection.cs index 5c35469..5148fc6 100644 --- a/CreamInstaller/ProgramSelection.cs +++ b/CreamInstaller/ProgramSelection.cs @@ -1,5 +1,4 @@ -using CG.Web.MegaApiClient; -using System.Collections.Generic; +using System.Collections.Generic; namespace CreamInstaller { @@ -7,10 +6,11 @@ namespace CreamInstaller { public bool Enabled = true; - public string ProgramName; - public string ProgramDirectory; + public string Name; + public string DisplayName; + public string RootDirectory; + public int SteamAppId; public List SteamApiDllDirectories; - public INode DownloadNode; public bool IsProgramRunning { diff --git a/CreamInstaller/Properties/launchSettings.json b/CreamInstaller/Properties/launchSettings.json index 2fdda68..07db735 100644 --- a/CreamInstaller/Properties/launchSettings.json +++ b/CreamInstaller/Properties/launchSettings.json @@ -1,6 +1,6 @@ { "profiles": { - "MEGA": { + "CreamInstaller": { "commandName": "Project", "nativeDebugging": false } diff --git a/CreamInstaller/SelectForm.cs b/CreamInstaller/SelectForm.cs index b011585..6d7c1e1 100644 --- a/CreamInstaller/SelectForm.cs +++ b/CreamInstaller/SelectForm.cs @@ -1,5 +1,4 @@ -using CG.Web.MegaApiClient; -using Gameloop.Vdf; +using Gameloop.Vdf; using Gameloop.Vdf.Linq; using Microsoft.Win32; using System; @@ -7,6 +6,7 @@ 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; @@ -27,12 +27,9 @@ namespace CreamInstaller get { List gameDirectories = new List(); - if (Program.Canceled) { return gameDirectories; } + if (Program.Canceled) return gameDirectories; string steamInstallPath = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Valve\\Steam", "InstallPath", null) as string; - if (steamInstallPath == null) - { - steamInstallPath = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Valve\\Steam", "InstallPath", null) as string; - } + if (steamInstallPath == null) steamInstallPath = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Valve\\Steam", "InstallPath", null) as string; if (steamInstallPath != null) { string mainLibraryFolder = steamInstallPath + "\\steamapps\\common"; @@ -40,160 +37,157 @@ namespace CreamInstaller string libraryFolders = steamInstallPath + "\\steamapps\\libraryfolders.vdf"; VProperty property = VdfConvert.Deserialize(File.ReadAllText(libraryFolders)); foreach (VProperty _property in property.Value) - { - if (int.TryParse(_property.Key, out _)) - { + if (int.TryParse(_property.Key, out _) && Directory.Exists(_property.Value.ToString())) gameDirectories.Add(_property.Value.ToString()); - } - } } return gameDirectories; } } - private List GetSteamApiDllDirectoriesFromGameDirectory(string gameDirectory, List steamApiDllDirectories = null) + private bool GetSteamApiDllDirectoriesFromGameDirectory(string gameDirectory, out List steamApiDllDirectories) { - if (Program.Canceled) { return null; } - if (steamApiDllDirectories is null) - { - steamApiDllDirectories = new(); - } - string file = gameDirectory + "\\steam_api64.dll"; - if (File.Exists(file)) - { - steamApiDllDirectories.Add(gameDirectory); - } + steamApiDllDirectories = new(); + if (Program.Canceled) return false; + 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)) { - if (Program.Canceled) { return null; } - GetSteamApiDllDirectoriesFromGameDirectory(_directory, steamApiDllDirectories); + if (Program.Canceled) return false; + try + { + if (GetSteamApiDllDirectoriesFromGameDirectory(_directory, out List _steamApiDllDirectories)) + steamApiDllDirectories.AddRange(_steamApiDllDirectories); + } + catch { } } - if (!steamApiDllDirectories.Any()) - { - return null; - } - return steamApiDllDirectories; + if (!steamApiDllDirectories.Any()) return false; + return true; } - private string GetGameDirectoryFromLibraryDirectory(string gameName, string libraryDirectory) + private bool GetSteamAppIdFromGameDirectory(string gameDirectory, out int appId) { - if (Program.Canceled) { return null; } - if (Path.GetFileName(libraryDirectory) == gameName) + appId = 0; + if (Program.Canceled) return false; + string file = gameDirectory + "\\steam_appid.txt"; + if (File.Exists(file) && int.TryParse(File.ReadAllText(file), out appId)) return true; + foreach (string _directory in Directory.GetDirectories(gameDirectory)) { - return libraryDirectory; + if (Program.Canceled) return false; + if (GetSteamAppIdFromGameDirectory(_directory, out appId)) return true; } - try + return false; + } + + private bool GetGameDirectoriesFromLibraryDirectory(string libraryDirectory, out List gameDirectories) + { + gameDirectories = new(); + if (Program.Canceled) return false; + foreach (string _directory in Directory.GetDirectories(libraryDirectory)) { - foreach (string _directory in Directory.GetDirectories(libraryDirectory)) - { - if (Program.Canceled) { return null; } - string dir = GetGameDirectoryFromLibraryDirectory(gameName, _directory); - if (dir != null) - { - return dir; - } - } + if (Program.Canceled) return false; + if (Directory.Exists(_directory)) gameDirectories.Add(_directory); } - catch { } - return null; + if (!gameDirectories.Any()) return false; + return true; } private readonly List checkBoxes = new(); + private readonly Dictionary dlc = new(); + + [DllImport("kernel32")] + private static extern bool AllocConsole(); + private void GetCreamApiApplicablePrograms(IProgress progress) { - if (Program.Canceled) { return; } - int maxProgress = 0; - IEnumerable fileNodes = Program.MegaApiClient.GetNodesFromLink(new Uri("https://mega.nz/folder/45YBwIxZ#fsZNZZu9twY2PVLgrB86fA")); - foreach (INode node in fileNodes) + if (Program.Canceled) return; + List> applicablePrograms = new(); + string launcherRootDirectory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Programs\\Paradox Interactive"; + if (Directory.Exists(launcherRootDirectory)) applicablePrograms.Add(new Tuple("Paradox Launcher", launcherRootDirectory)); + foreach (string libraryDirectory in GameLibraryDirectories) + 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(); + foreach (Tuple program in applicablePrograms) { - if (Program.Canceled) { return; } - if (node.Type == NodeType.Directory && node.Name != "CreamAPI" && node.Name != "Outdated") + string name = program.Item1; + string rootDirectory = program.Item2; + if (Program.Canceled) return; + Task task = new Task(() => { - ++maxProgress; - } - } - progress.Report(maxProgress); - int curProgress = 0; - progress.Report(curProgress); - foreach (INode node in fileNodes) - { - if (Program.Canceled) { return; } - if (node.Type == NodeType.Directory && node.Name != "CreamAPI" && node.Name != "Outdated") - { - progress.Report(++curProgress); - if (Program.ProgramSelections.Any(selection => selection.ProgramName == node.Name)) { continue; } - string rootDirectory = null; - List directories = null; - if (node.Name == "Paradox Launcher") + 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)) { - rootDirectory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Programs\\Paradox Interactive"; - if (Directory.Exists(rootDirectory)) + 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) { - directories = GetSteamApiDllDirectoriesFromGameDirectory(rootDirectory); + 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); } } - else + else if (name != "Paradox Launcher") 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; + + flowLayoutPanel1.Invoke((MethodInvoker)delegate { - foreach (string libraryDirectory in GameLibraryDirectories) + 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; + + checkBox.CheckedChanged += (sender, e) => { - if (Program.Canceled) { return; } - rootDirectory = GetGameDirectoryFromLibraryDirectory(node.Name, libraryDirectory); - if (Directory.Exists(rootDirectory)) - { - directories = GetSteamApiDllDirectoriesFromGameDirectory(rootDirectory); - break; - } - } - } - if (!(directories is null)) - { - if (Program.Canceled) { return; } - flowLayoutPanel1.Invoke((MethodInvoker)delegate - { - if (Program.Canceled) { return; } - - INode downloadNode = null; - foreach (INode _node in fileNodes) - { - if (_node.Type == NodeType.File && _node.ParentId == node.Id) - { - downloadNode = _node; - break; - } - } - - if (downloadNode is null) return; - ProgramSelection selection = new(); - selection.DownloadNode = downloadNode; - selection.ProgramName = node.Name; - selection.ProgramDirectory = rootDirectory; - selection.SteamApiDllDirectories = new(); - selection.SteamApiDllDirectories.AddRange(directories); - - CheckBox checkBox = new(); - checkBoxes.Add(checkBox); - checkBox.AutoSize = true; - checkBox.Parent = flowLayoutPanel1; - checkBox.Text = node.Name; - checkBox.Checked = true; - checkBox.Enabled = false; - checkBox.TabStop = true; - checkBox.TabIndex = 1 + checkBoxes.Count; - - checkBox.CheckedChanged += (sender, e) => - { - 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; - }; - }); - } - } + 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; + }; + }); + }); + tasks.Add(task); + task.Start(); } - progress.Report(maxProgress); + int max = tasks.Count; + progress.Report(max); + int cur = 0; + progress.Report(cur); + foreach (Task task in tasks) + { + progress.Report(cur++); + task.Wait(); + } + progress.Report(max); } private async void OnLoad() @@ -211,29 +205,48 @@ namespace CreamInstaller progressBar1.Value = 0; groupBox1.Size = new Size(groupBox1.Size.Width, groupBox1.Size.Height - 44); - label2.Text = "Scanning for CreamAPI-applicable programs on your computer . . . "; + AllocConsole(); + + bool setup = true; int maxProgress = 0; Progress progress = new(); + IProgress iProgress = progress; progress.ProgressChanged += (sender, _progress) => { - if (maxProgress == 0) - { - maxProgress = _progress; - } + if (maxProgress == 0) maxProgress = _progress; else { - int p = (int)((float)(_progress / (float)maxProgress) * 100); - label2.Text = "Scanning for CreamAPI-applicable programs on your computer . . . " + p + "% (" + _progress + "/" + maxProgress + ")"; + 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; } }; - await Task.Run(() => GetCreamApiApplicablePrograms(progress)); + + int max = 1660; // not exact, number varies + iProgress.Report(max); + int cur = 0; + iProgress.Report(cur); + label2.Text = "Setting up SteamCMD . . . "; + FileSystemWatcher watcher = new FileSystemWatcher(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 . . . "; + await Task.Run(() => GetCreamApiApplicablePrograms(iProgress)); Program.ProgramSelections.ForEach(selection => selection.SteamApiDllDirectories.RemoveAll(directory => !Directory.Exists(directory))); - Program.ProgramSelections.RemoveAll(selection => !Directory.Exists(selection.ProgramDirectory) || !selection.SteamApiDllDirectories.Any()); + Program.ProgramSelections.RemoveAll(selection => !Directory.Exists(selection.RootDirectory) || !selection.SteamApiDllDirectories.Any()); foreach (CheckBox checkBox in checkBoxes) { - if (!Program.ProgramSelections.Any(selection => selection.ProgramName == checkBox.Text)) + if (!Program.ProgramSelections.Any(selection => selection.DisplayName == checkBox.Text)) { checkBox.Dispose(); } @@ -289,8 +302,8 @@ namespace CreamInstaller checkBox.Checked = !checkBox.Checked; checkBox.Checked = !checkBox.Checked; // to fire CheckChanged } - int X = (installForm.Location.X + installForm.Size.Width / 2) - Size.Width / 2; - int Y = (installForm.Location.Y + installForm.Size.Height / 2) - Size.Height / 2; + 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); Show(); } @@ -308,7 +321,7 @@ namespace CreamInstaller private void OnCancel(object sender, EventArgs e) { - Program.Cleanup(logout: false); + Program.Cleanup(); } private void OnAllCheckBoxChanged(object sender, EventArgs e) diff --git a/CreamInstaller/SteamCMD.cs b/CreamInstaller/SteamCMD.cs new file mode 100644 index 0000000..1d37e35 --- /dev/null +++ b/CreamInstaller/SteamCMD.cs @@ -0,0 +1,77 @@ +using SteamCmdFluentApi; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Net; + +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"; + + private static SteamCmd current = null; + + public static SteamCmd Current + { + get + { + if (current is null) current = SteamCmd.WithExecutable(FilePath); + return current; + } + } + + 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); + ZipFile.ExtractToDirectory(ArchivePath, DirectoryPath); + File.Delete(ArchivePath); + } + if (!File.Exists(DllPath)) Current.TryToExecuteCommand($@"+login anonymous +app_info_update 1 +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; + foreach (string s in output.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)) + { + int first = s.IndexOf("\""); + int second = 1 + first + s.Substring(first + 1).IndexOf("\""); + int third = 1 + second + s.Substring(second + 1).IndexOf("\""); + int fourth = 1 + third + s.Substring(third + 1).IndexOf("\""); + if (first > -1 && second > 0 && third > 0 && fourth > 0) + { + string a = s.Substring(first + 1, Math.Max(second - first - 1, 0)); + string b = s.Substring(third + 1, Math.Max(fourth - third - 1, 0)); + if (string.IsNullOrWhiteSpace(a) || string.IsNullOrWhiteSpace(b)) continue; + if (!appInfo.TryGetValue(a, out _)) appInfo.Add(a, b); + } + } + return true; + } + + public static void Kill() + { + foreach (Process process in Process.GetProcessesByName("steamcmd")) { process.Kill(); process.WaitForExit(); } + } + + public static void Dispose() + { + Kill(); + if (Directory.Exists(DirectoryPath)) Directory.Delete(DirectoryPath, true); + } + } +} \ No newline at end of file