diff --git a/CreamInstaller/CreamInstaller.csproj b/CreamInstaller/CreamInstaller.csproj index 7b44ed8..7d85488 100644 --- a/CreamInstaller/CreamInstaller.csproj +++ b/CreamInstaller/CreamInstaller.csproj @@ -9,7 +9,7 @@ 2.0.0.0 ini.ico - Automatically downloads and installs CreamAPI files for programs/games. + Automatically generates and installs CreamAPI files for programs/games. LICENSE 2021, pointfeev (https://github.com/pointfeev) true @@ -20,7 +20,7 @@ steam, dlc CreamInstaller CreamInstaller - CreamAPI Downloader & Installer + CreamAPI Generator & Installer pointfeev pointfeev.creaminstaller CreamInstaller.Program @@ -32,6 +32,19 @@ TRACE + + + + + + + + + + + + + diff --git a/CreamInstaller/InstallForm.cs b/CreamInstaller/InstallForm.cs index 823fd6e..231e6a4 100644 --- a/CreamInstaller/InstallForm.cs +++ b/CreamInstaller/InstallForm.cs @@ -2,8 +2,9 @@ using System.Collections.Generic; 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 @@ -27,7 +28,7 @@ namespace CreamInstaller public void UpdateProgress(int progress) { int value = (int)((float)(CompleteOperationsCount / (float)OperationsCount) * 100) + (progress / OperationsCount); - if (value < userProgressBar.Value) { return; } + if (value < userProgressBar.Value) return; userProgressBar.Value = value; } @@ -40,125 +41,96 @@ namespace CreamInstaller { logTextBox.AppendText(Environment.NewLine, color); } - logTextBox.AppendText(userInfoLabel.Text, color); } } - private void OperateFor(ProgramSelection selection) + private async Task OperateFor(ProgramSelection selection) { UpdateProgress(0); - 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; - List resources = new List(); - Program.OutputArchive = ZipFile.OpenRead(Program.OutputFile); - int currentEntryCount = 0; - foreach (ZipArchiveEntry entry in Program.OutputArchive.Entries) - { - currentEntryCount++; - if (entry.Name == "steam_api64.dll") - { - resourcePath = Path.GetDirectoryName(entry.FullName); - UpdateUser("Got CreamAPI file path: " + resourcePath, LogColor.Resource); - } - UpdateProgress(currentEntryCount / (Program.OutputArchive.Entries.Count * 2) * 100); - } - foreach (ZipArchiveEntry entry in Program.OutputArchive.Entries) - { - currentEntryCount++; - if (!string.IsNullOrEmpty(entry.Name) && Path.GetDirectoryName(entry.FullName) == resourcePath) - { - resources.Add(entry); - UpdateUser("Found CreamAPI file: " + entry.Name, LogColor.Resource); - } - UpdateProgress(currentEntryCount / (Program.OutputArchive.Entries.Count * 2) * 100); - } - if (resources.Count < 1) - { - throw new CustomMessageException($"Unable to find CreamAPI files in downloaded archive: {Program.OutputFile}"); - } - if (!Program.IsProgramRunningDialog(this, selection)) - { - throw new OperationCanceledException(); - } - UpdateUser("Installing CreamAPI files for " + selection.DisplayName + " . . . ", LogColor.Operation); - int currentFileCount = 0; + int count = selection.SteamApiDllDirectories.Count; + int cur = 0; foreach (string directory in selection.SteamApiDllDirectories) { - Dictionary changesToRevert = new(); - foreach (ZipArchiveEntry entry in resources) + UpdateUser("Installing CreamAPI for " + selection.DisplayName + $" in directory \"{directory}\" . . . ", LogColor.Operation); + if (!Program.IsProgramRunningDialog(this, selection)) throw new OperationCanceledException(); + string api = directory + @"\steam_api.dll"; + string api_o = directory + @"\steam_api_o.dll"; + if (File.Exists(api) && !File.Exists(api_o)) { - currentFileCount++; - string file = directory + "\\" + entry.Name; - if (File.Exists(file)) - { - string backup = file + Program.BackupFileExtension; - File.Copy(file, backup, true); - changesToRevert.Add(file, backup); - } - else - { - changesToRevert.Add(file, string.Empty); - } - try - { - entry.ExtractToFile(file, true); - } - catch - { - foreach (KeyValuePair keyValuePair in changesToRevert) - { - file = keyValuePair.Key; - string backup = keyValuePair.Value; - if (string.IsNullOrEmpty(backup)) - { - File.Delete(file); - UpdateUser("Deleted CreamAPI file: " + file, LogColor.Warning); - } - else if (file.IsFilePathLocked()) - { - File.Delete(backup); - } - else - { - File.Move(backup, file, true); - UpdateUser("Reversed changes to Steam API file: " + file, LogColor.Warning); - } - } - throw new CustomMessageException($"Unable to overwrite Steam API file: {file}"); - } - UpdateUser("Installed file: " + file, LogColor.Resource); - UpdateProgress(currentFileCount / (resources.Count * selection.SteamApiDllDirectories.Count) * 100); + File.Move(api, api_o); + UpdateUser($"Renamed file: {api} -> steam_api_o.dll", LogColor.Resource); } - foreach (KeyValuePair keyValuePair in changesToRevert) + if (File.Exists(api_o)) { - string file = keyValuePair.Key; - string backup = keyValuePair.Value; - if (!string.IsNullOrEmpty(backup)) + Resources.WriteResourceToFile("steam_api.dll", api); + UpdateUser($"Wrote resource to file: {api}", LogColor.Resource); + } + string api64 = directory + @"\steam_api64.dll"; + string api64_o = directory + @"\steam_api64_o.dll"; + if (File.Exists(api64) && !File.Exists(api64_o)) + { + File.Move(api64, api64_o); + UpdateUser($"Renamed file: {api64} -> steam_api64_o.dll", LogColor.Resource); + } + if (File.Exists(api64_o)) + { + Resources.WriteResourceToFile("steam_api64.dll", api64); + UpdateUser($"Wrote resource to file: {api64}", LogColor.Resource); + } + string cApi = directory + @"\cream_api.ini"; + File.Create(cApi).Close(); + StreamWriter writer = File.AppendText(cApi); + writer.WriteLine(";Created with CreamInstaller by pointfeev#4538"); + if (selection.SteamAppId > 0) + { + writer.WriteLine(); + writer.WriteLine("[steam]"); + writer.WriteLine($"appid = {selection.SteamAppId}"); + writer.WriteLine(); + writer.WriteLine("[dlc]"); + UpdateUser($"Added game to cream_api.ini with appid {selection.SteamAppId} ({selection.DisplayName})", LogColor.Resource); + foreach (Tuple dlcApp in selection.SelectedSteamDlc) { - File.Delete(backup); + writer.WriteLine($"{dlcApp.Item1} = {dlcApp.Item2}"); + UpdateUser($"Added DLC to cream_api.ini with appid {dlcApp.Item1} ({dlcApp.Item2})", LogColor.Resource); } } + foreach (Tuple>> extraAppDlc in selection.ExtraSteamAppIdDlc) + { + writer.WriteLine(); + writer.WriteLine("[steam]"); + writer.WriteLine($"appid = {extraAppDlc.Item1}"); + writer.WriteLine(); + writer.WriteLine("[dlc]"); + UpdateUser($"Added game to cream_api.ini with appid {extraAppDlc.Item1} ({extraAppDlc.Item2})", LogColor.Resource); + foreach (Tuple dlcApp in extraAppDlc.Item3) + { + writer.WriteLine($"{dlcApp.Item1} = {dlcApp.Item2}"); + UpdateUser($"Added DLC to cream_api.ini with appid {dlcApp.Item1} ({dlcApp.Item2})", LogColor.Resource); + } + } + writer.Flush(); + writer.Close(); + await Task.Run(() => Thread.Sleep(0)); // to keep the text box control from glitching + UpdateProgress(++cur / count * 100); } UpdateProgress(100); } - private void Operate() + private async Task Operate() { - OperationsCount = Program.ProgramSelections.ToList().FindAll(selection => selection.Enabled).Count; + OperationsCount = ProgramSelection.AllSafeEnabled.Count; CompleteOperationsCount = 0; - - foreach (ProgramSelection selection in Program.ProgramSelections.ToList()) + foreach (ProgramSelection selection in ProgramSelection.AllSafe) { if (!selection.Enabled) continue; if (!Program.IsProgramRunningDialog(this, selection)) throw new OperationCanceledException(); try { - OperateFor(selection); + await OperateFor(selection); UpdateUser($"Operation succeeded for {selection.DisplayName}.", LogColor.Success); - selection.Toggle(false); + selection.Enabled = false; } catch (Exception exception) { @@ -167,7 +139,7 @@ namespace CreamInstaller ++CompleteOperationsCount; } Program.Cleanup(); - List FailedSelections = Program.ProgramSelections.ToList().FindAll(selection => selection.Enabled); + List FailedSelections = ProgramSelection.AllSafeEnabled; if (FailedSelections.Any()) { if (FailedSelections.Count == 1) @@ -181,9 +153,9 @@ namespace CreamInstaller } } - private readonly int ProgramCount = Program.ProgramSelections.ToList().FindAll(selection => selection.Enabled).Count; + private readonly int ProgramCount = ProgramSelection.AllSafeEnabled.Count; - private void Start() + private async void Start() { acceptButton.Enabled = false; retryButton.Enabled = false; @@ -192,12 +164,12 @@ namespace CreamInstaller userProgressBar.Value = userProgressBar.Minimum; try { - Operate(); - UpdateUser("CreamAPI successfully downloaded and installed for " + ProgramCount + " program(s).", LogColor.Success); + await Operate(); + UpdateUser("CreamAPI successfully installed for " + ProgramCount + " program(s).", LogColor.Success); } catch (Exception exception) { - UpdateUser("CreamAPI download and/or installation failed: " + exception.ToString(), LogColor.Error); + UpdateUser("CreamAPI installation failed: " + exception.ToString(), LogColor.Error); retryButton.Enabled = true; } userProgressBar.Value = userProgressBar.Maximum; diff --git a/CreamInstaller/Program.cs b/CreamInstaller/Program.cs index 419461d..bb7c63d 100644 --- a/CreamInstaller/Program.cs +++ b/CreamInstaller/Program.cs @@ -12,7 +12,7 @@ namespace CreamInstaller { public static class Program { - public static readonly string ApplicationName = "CreamInstaller v" + Application.ProductVersion + ": CreamAPI Downloader & Installer"; + public static readonly string ApplicationName = Application.CompanyName + " v" + Application.ProductVersion + ": " + Application.ProductName; public static readonly Assembly EntryAssembly = Assembly.GetEntryAssembly(); public static readonly Process CurrentProcess = Process.GetCurrentProcess(); public static readonly string CurrentProcessFilePath = CurrentProcess.MainModule.FileName; @@ -36,7 +36,7 @@ namespace CreamInstaller public static bool IsProgramRunningDialog(Form form, ProgramSelection selection) { - if (selection.IsProgramRunning) + if (selection.AreSteamApiDllsLocked) { if (new DialogForm(form).Show(ApplicationName, SystemIcons.Error, $"ERROR: {selection.DisplayName} is currently running!" + @@ -55,6 +55,7 @@ namespace CreamInstaller public static bool IsFilePathLocked(this string filePath) { + if (!File.Exists(filePath)) return false; bool Locked = false; try { diff --git a/CreamInstaller/ProgramSelection.cs b/CreamInstaller/ProgramSelection.cs index 58f328a..56a6561 100644 --- a/CreamInstaller/ProgramSelection.cs +++ b/CreamInstaller/ProgramSelection.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; namespace CreamInstaller { @@ -12,21 +14,54 @@ namespace CreamInstaller public int SteamAppId; public List SteamApiDllDirectories; - public bool IsProgramRunning + public Dictionary AppInfo = new(); + public List> AllSteamDlc = new(); + public List> SelectedSteamDlc = new(); + public List>>> ExtraSteamAppIdDlc = new(); + + public bool AreSteamApiDllsLocked { get { foreach (string directory in SteamApiDllDirectories) { - string file = directory + "\\steam_api64.dll"; - if (file.IsFilePathLocked()) return true; + string api = directory + @"\steam_api.dll"; + string api64 = directory + @"\steam_api64.dll"; + if (api.IsFilePathLocked() || api64.IsFilePathLocked()) return true; } return false; } } - public ProgramSelection() => Program.ProgramSelections.Add(this); + public void ToggleDlc(string dlcName, bool Enabled) + { + foreach (Tuple dlcApp in AllSteamDlc) + { + if (dlcApp.Item2 == dlcName) + { + if (Enabled) + { + if (!SelectedSteamDlc.Contains(dlcApp)) + { + SelectedSteamDlc.Add(dlcApp); + } + } + else SelectedSteamDlc.Remove(dlcApp); + return; + } + } + } - public void Toggle(bool Enabled) => this.Enabled = Enabled; + public ProgramSelection() => All.Add(this); + + public static List All => Program.ProgramSelections; + + public static List AllSafe => All.ToList(); + + public static List AllSafeEnabled => AllSafe.FindAll(s => s.Enabled); + + public static ProgramSelection FromIdentifier(string identifier) => AllSafe.Find(s => s.Identifier == identifier); + + public static ProgramSelection FromDisplayName(string displayName) => AllSafe.Find(s => s.DisplayName == displayName); } } \ No newline at end of file diff --git a/CreamInstaller/Resources.cs b/CreamInstaller/Resources.cs new file mode 100644 index 0000000..cfaf885 --- /dev/null +++ b/CreamInstaller/Resources.cs @@ -0,0 +1,15 @@ +using System.IO; +using System.Reflection; + +namespace CreamInstaller +{ + public static class Resources + { + public static void WriteResourceToFile(string resourceName, string filePath) + { + using Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream("CreamInstaller." + resourceName); + using FileStream file = new(filePath, FileMode.Create, FileAccess.Write); + resource.CopyTo(file); + } + } +} \ No newline at end of file diff --git a/CreamInstaller/SelectForm.cs b/CreamInstaller/SelectForm.cs index aaaf554..45dca0b 100644 --- a/CreamInstaller/SelectForm.cs +++ b/CreamInstaller/SelectForm.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Forms; @@ -47,8 +48,8 @@ namespace CreamInstaller { steamApiDllDirectories = new(); if (Program.Canceled) return false; - string api = gameDirectory + "\\steam_api.dll"; - string api64 = gameDirectory + "\\steam_api64.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)) { @@ -138,17 +139,17 @@ namespace CreamInstaller if (!(appInfo is null) && appInfo.TryGetValue("listofdlc", out list)) { if (Program.Canceled) return; + string[] nums = Regex.Replace(list, "[^0-9,]+", "").Split(","); + List ids = new(); + foreach (string s in nums) + { + if (Program.Canceled) return; + ids.Add(int.Parse(s)); + } 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; @@ -156,7 +157,7 @@ namespace CreamInstaller Dictionary dlcAppInfo = null; if (SteamCMD.GetAppInfo(id, out dlcAppInfo)) dlcAppInfo.TryGetValue("name", out dlcName); if (Program.Canceled) return; - if (string.IsNullOrWhiteSpace(dlcName)) continue; + if (string.IsNullOrWhiteSpace(dlcName)) dlcName = "Unknown DLC"; dlc.Add(new Tuple(id, dlcName)); } } @@ -170,17 +171,19 @@ namespace CreamInstaller else if (identifier != "Paradox Launcher") return; if (Program.Canceled) return; + if (string.IsNullOrWhiteSpace(identifier)) return; string displayName = identifier; if (!(appInfo is null)) appInfo.TryGetValue("name", out displayName); - if (string.IsNullOrWhiteSpace(displayName)) return; + if (string.IsNullOrWhiteSpace(displayName)) displayName = "Unknown Game"; if (Program.Canceled) return; - ProgramSelection selection = Program.ProgramSelections.Find(s => s.Identifier == identifier) ?? new(); + ProgramSelection selection = ProgramSelection.FromIdentifier(identifier) ?? new(); selection.Identifier = identifier; selection.DisplayName = displayName; selection.RootDirectory = rootDirectory; selection.SteamAppId = steamAppId; selection.SteamApiDllDirectories = steamApiDllDirectories; + selection.AppInfo = appInfo; foreach (Task task in dlcTasks.ToList()) { @@ -207,6 +210,8 @@ namespace CreamInstaller programNode.Nodes.Add(dlcNode); treeNodes.Remove(dlcNode); treeNodes.Add(dlcNode); + selection.AllSteamDlc.Add(dlcApp); + selection.SelectedSteamDlc.Add(dlcApp); } }); } @@ -273,11 +278,11 @@ namespace CreamInstaller 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()); + ProgramSelection.All.ForEach(selection => selection.SteamApiDllDirectories.RemoveAll(directory => !Directory.Exists(directory))); + ProgramSelection.All.RemoveAll(selection => !Directory.Exists(selection.RootDirectory) || !selection.SteamApiDllDirectories.Any()); foreach (TreeNode treeNode in treeNodes) { - if (treeNode.Parent is null && !Program.ProgramSelections.Any(selection => selection.DisplayName == treeNode.Text)) + if (treeNode.Parent is null && ProgramSelection.FromDisplayName(treeNode.Text) is null) { treeNode.Remove(); } @@ -288,13 +293,13 @@ namespace CreamInstaller label2.Visible = false; progressBar1.Visible = false; - if (Program.ProgramSelections.Any()) + if (ProgramSelection.All.Any()) { allCheckBox.Enabled = true; treeView1.CheckBoxes = true; treeView1.ExpandAll(); treeNodes.ForEach(node => node.Checked = true); - if (Program.ProgramSelections.Any(selection => selection.Enabled)) + if (ProgramSelection.AllSafeEnabled.Any()) { acceptButton.Enabled = true; } @@ -310,20 +315,22 @@ namespace CreamInstaller private void OnTreeViewNodeCheckedChanged(object sender, TreeViewEventArgs e) { - ProgramSelection selection = Program.ProgramSelections.ToList().Find(selection => selection.DisplayName == e.Node.Text); + ProgramSelection selection = ProgramSelection.FromDisplayName(e.Node.Text); if (selection is null) { + selection = ProgramSelection.FromDisplayName(e.Node.Parent.Text); treeView1.AfterCheck -= OnTreeViewNodeCheckedChanged; e.Node.Parent.Checked = e.Node.Parent.Nodes.Cast().ToList().Any(treeNode => treeNode.Checked); treeView1.AfterCheck += OnTreeViewNodeCheckedChanged; + selection.ToggleDlc(e.Node.Text, e.Node.Checked); } else { - selection.Toggle(e.Node.Checked); + selection.Enabled = e.Node.Checked; treeView1.AfterCheck -= OnTreeViewNodeCheckedChanged; e.Node.Nodes.Cast().ToList().ForEach(treeNode => treeNode.Checked = e.Node.Checked); treeView1.AfterCheck += OnTreeViewNodeCheckedChanged; - acceptButton.Enabled = Program.ProgramSelections.ToList().Any(selection => selection.Enabled); + acceptButton.Enabled = ProgramSelection.AllSafeEnabled.Any(); allCheckBox.CheckedChanged -= OnAllCheckBoxChanged; allCheckBox.Checked = treeNodes.TrueForAll(treeNode => treeNode.Checked); allCheckBox.CheckedChanged += OnAllCheckBoxChanged; @@ -339,9 +346,9 @@ namespace CreamInstaller private void OnAccept(object sender, EventArgs e) { - if (Program.ProgramSelections.Count > 0) + if (ProgramSelection.All.Count > 0) { - foreach (ProgramSelection selection in Program.ProgramSelections.ToList()) + foreach (ProgramSelection selection in ProgramSelection.AllSafe) { if (!Program.IsProgramRunningDialog(this, selection)) { @@ -349,16 +356,28 @@ namespace CreamInstaller } } + ProgramSelection paradoxLauncher = ProgramSelection.FromIdentifier("Paradox Launcher"); + if (!(paradoxLauncher is null)) + { + paradoxLauncher.ExtraSteamAppIdDlc = new(); + foreach (ProgramSelection selection in ProgramSelection.AllSafeEnabled) + { + if (selection.Identifier == paradoxLauncher.Identifier) continue; + if (!selection.AppInfo.TryGetValue("publisher", out string publisher) || publisher != "Paradox Interactive") continue; + paradoxLauncher.ExtraSteamAppIdDlc.Add(new(selection.SteamAppId, selection.DisplayName, selection.SelectedSteamDlc)); + } + } + Hide(); InstallForm installForm = new InstallForm(this); installForm.ShowDialog(); if (installForm.Reselecting) { - //foreach (TreeNode treeNode in treeNodes) - //{ - // treeNode.Checked = !treeNode.Checked; - // treeNode.Checked = !treeNode.Checked; // to fire checked event - //} + 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); diff --git a/CreamInstaller/SteamCMD.cs b/CreamInstaller/SteamCMD.cs index 7598a1a..92a47ab 100644 --- a/CreamInstaller/SteamCMD.cs +++ b/CreamInstaller/SteamCMD.cs @@ -13,7 +13,7 @@ namespace 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 AppUpdatePath = DirectoryPath + @"\appupdate"; + public static string AppInfoCachePath = DirectoryPath + @"\appinfocache"; public static bool Run(string command, out string output) { @@ -57,17 +57,16 @@ namespace CreamInstaller { appInfo = new(); if (Program.Canceled) return false; - string output = null; - string appUpdatePath = $@"{AppUpdatePath}\{steamAppId}"; + string output; + string appUpdatePath = $@"{AppInfoCachePath}\{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 (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 _); + 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)) { diff --git a/CreamInstaller/steam_api.dll b/CreamInstaller/steam_api.dll new file mode 100644 index 0000000..7babc7a Binary files /dev/null and b/CreamInstaller/steam_api.dll differ diff --git a/CreamInstaller/steam_api64.dll b/CreamInstaller/steam_api64.dll new file mode 100644 index 0000000..6ed8437 Binary files /dev/null and b/CreamInstaller/steam_api64.dll differ