initial framework for v2.0

This commit is contained in:
pointfeev 2021-10-29 04:20:27 -04:00
parent d24ba494de
commit f5ba69f380
No known key found for this signature in database
GPG key ID: AA14DC36C4D7D13C
8 changed files with 271 additions and 296 deletions

View file

@ -6,7 +6,7 @@
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>ini.ico</ApplicationIcon>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
<Version>1.0.6.4</Version>
<Version>2.0.0.0</Version>
<PackageIcon>ini.ico</PackageIcon>
<PackageIconUrl />
<Description>Automatically downloads and installs CreamAPI files for programs/games.</Description>
@ -34,7 +34,7 @@
<ItemGroup>
<PackageReference Include="Gameloop.Vdf" Version="0.6.1" />
<PackageReference Include="MegaApiClient" Version="1.9.0" />
<PackageReference Include="koskit.SteamCmdFluentApi" Version="1.0.4" />
<PackageReference Include="Onova" Version="2.6.2" />
</ItemGroup>

View file

@ -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<double> progress = new Progress<double>(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<string, string> 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<ProgramSelection> 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();
}

View file

@ -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();
}

View file

@ -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<ProgramSelection> 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();
}
}

View file

@ -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<string> SteamApiDllDirectories;
public INode DownloadNode;
public bool IsProgramRunning
{

View file

@ -1,6 +1,6 @@
{
"profiles": {
"MEGA": {
"CreamInstaller": {
"commandName": "Project",
"nativeDebugging": false
}

View file

@ -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<string> gameDirectories = new List<string>();
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<string> GetSteamApiDllDirectoriesFromGameDirectory(string gameDirectory, List<string> steamApiDllDirectories = null)
private bool GetSteamApiDllDirectoriesFromGameDirectory(string gameDirectory, out List<string> 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<string> _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<string> 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<CheckBox> checkBoxes = new();
private readonly Dictionary<int, string> dlc = new();
[DllImport("kernel32")]
private static extern bool AllocConsole();
private void GetCreamApiApplicablePrograms(IProgress<int> progress)
{
if (Program.Canceled) { return; }
int maxProgress = 0;
IEnumerable<INode> fileNodes = Program.MegaApiClient.GetNodesFromLink(new Uri("https://mega.nz/folder/45YBwIxZ#fsZNZZu9twY2PVLgrB86fA"));
foreach (INode node in fileNodes)
if (Program.Canceled) return;
List<Tuple<string, string>> applicablePrograms = new();
string launcherRootDirectory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Programs\\Paradox Interactive";
if (Directory.Exists(launcherRootDirectory)) applicablePrograms.Add(new Tuple<string, string>("Paradox Launcher", launcherRootDirectory));
foreach (string libraryDirectory in GameLibraryDirectories)
if (GetGameDirectoriesFromLibraryDirectory(libraryDirectory, out List<string> gameDirectories))
foreach (string gameDirectory in gameDirectories)
applicablePrograms.Add(new Tuple<string, string>(Path.GetFileName(gameDirectory) ?? "unknown_" + applicablePrograms.Count, gameDirectory));
List<Task> tasks = new();
foreach (Tuple<string, string> 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<string> 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<string> steamApiDllDirectories))
return;
Dictionary<string, string> 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<int> 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<string, string> 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<int> progress = new();
IProgress<int> 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)

View file

@ -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<string, string> 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);
}
}
}