v2.4.3.0
- Minor code refactoring - Added a Paradox Launcher Repair feature to the right-click context menu
This commit is contained in:
parent
cbf614c04d
commit
b9d84c0c34
6 changed files with 196 additions and 88 deletions
|
@ -33,9 +33,13 @@ internal class ProgramSelection
|
|||
{
|
||||
foreach (string directory in SteamApiDllDirectories)
|
||||
{
|
||||
string api = directory + @"\steam_api.dll";
|
||||
string api64 = directory + @"\steam_api64.dll";
|
||||
if (api.IsFilePathLocked() || api64.IsFilePathLocked()) return true;
|
||||
directory.GetApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string cApi);
|
||||
if (api.IsFilePathLocked()
|
||||
|| api_o.IsFilePathLocked()
|
||||
|| api64.IsFilePathLocked()
|
||||
|| api64_o.IsFilePathLocked()
|
||||
|| cApi.IsFilePathLocked())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,10 @@ internal partial class DialogForm : CustomForm
|
|||
{
|
||||
internal DialogForm(IWin32Window owner) : base(owner) => InitializeComponent();
|
||||
|
||||
internal DialogResult Show(string formName, Icon descriptionIcon, string descriptionText, string acceptButtonText, string cancelButtonText = null)
|
||||
internal DialogResult Show(string formName, Icon descriptionIcon, string descriptionText, string acceptButtonText, string cancelButtonText = null, Icon customFormIcon = null)
|
||||
{
|
||||
if (customFormIcon is not null)
|
||||
Icon = customFormIcon;
|
||||
icon.Image = descriptionIcon.ToBitmap();
|
||||
Text = formName;
|
||||
descriptionLabel.Text = descriptionText;
|
||||
|
|
|
@ -4,7 +4,6 @@ using System.Drawing;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
|
@ -32,24 +31,30 @@ internal partial class InstallForm : CustomForm
|
|||
private int CompleteOperationsCount;
|
||||
|
||||
internal void UpdateProgress(int progress)
|
||||
{
|
||||
if (!userProgressBar.Disposing && !userProgressBar.IsDisposed)
|
||||
userProgressBar.Invoke(() =>
|
||||
{
|
||||
int value = (int)((float)(CompleteOperationsCount / (float)OperationsCount) * 100) + progress / OperationsCount;
|
||||
if (value < userProgressBar.Value) return;
|
||||
userProgressBar.Value = value;
|
||||
});
|
||||
}
|
||||
|
||||
internal async Task UpdateUser(string text, Color color, bool info = true, bool log = true)
|
||||
internal void UpdateUser(string text, Color color, bool info = true, bool log = true)
|
||||
{
|
||||
if (info) userInfoLabel.Text = text;
|
||||
if (log && !logTextBox.IsDisposed)
|
||||
if (info) userInfoLabel.Invoke(() => userInfoLabel.Text = text);
|
||||
if (log && !logTextBox.Disposing && !logTextBox.IsDisposed)
|
||||
{
|
||||
logTextBox.Invoke(() =>
|
||||
{
|
||||
if (logTextBox.Text.Length > 0) logTextBox.AppendText(Environment.NewLine, color);
|
||||
logTextBox.AppendText(text, color);
|
||||
});
|
||||
}
|
||||
await Task.Run(() => Thread.Sleep(0)); // to keep the text box control from glitching
|
||||
}
|
||||
|
||||
internal async Task WriteConfiguration(StreamWriter writer, int steamAppId, string name, SortedList<int, (string name, string iconStaticId)> steamDlcApps)
|
||||
internal static void WriteConfiguration(StreamWriter writer, int steamAppId, string name, SortedList<int, (string name, string iconStaticId)> steamDlcApps, InstallForm installForm = null)
|
||||
{
|
||||
writer.WriteLine();
|
||||
writer.WriteLine($"; {name}");
|
||||
|
@ -57,16 +62,93 @@ internal partial class InstallForm : CustomForm
|
|||
writer.WriteLine($"appid = {steamAppId}");
|
||||
writer.WriteLine();
|
||||
writer.WriteLine("[dlc]");
|
||||
await UpdateUser($"Added game to cream_api.ini with appid {steamAppId} ({name})", InstallationLog.Resource, info: false);
|
||||
if (installForm is not null)
|
||||
installForm.UpdateUser($"Added game to cream_api.ini with appid {steamAppId} ({name})", InstallationLog.Resource, info: false);
|
||||
foreach (KeyValuePair<int, (string name, string iconStaticId)> pair in steamDlcApps)
|
||||
{
|
||||
int appId = pair.Key;
|
||||
(string name, string iconStaticId) dlcApp = pair.Value;
|
||||
writer.WriteLine($"{appId} = {dlcApp.name}");
|
||||
await UpdateUser($"Added DLC to cream_api.ini with appid {appId} ({dlcApp.name})", InstallationLog.Resource, info: false);
|
||||
if (installForm is not null)
|
||||
installForm.UpdateUser($"Added DLC to cream_api.ini with appid {appId} ({dlcApp.name})", InstallationLog.Resource, info: false);
|
||||
}
|
||||
}
|
||||
|
||||
internal static async Task UninstallCreamAPI(string directory, InstallForm installForm = null) => await Task.Run(() =>
|
||||
{
|
||||
directory.GetApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string cApi);
|
||||
if (File.Exists(api_o))
|
||||
{
|
||||
if (File.Exists(api))
|
||||
{
|
||||
File.Delete(api);
|
||||
if (installForm is not null)
|
||||
installForm.UpdateUser($"Deleted file: {Path.GetFileName(api)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
File.Move(api_o, api);
|
||||
if (installForm is not null)
|
||||
installForm.UpdateUser($"Renamed file: {Path.GetFileName(api_o)} -> {Path.GetFileName(api)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
if (File.Exists(api64_o))
|
||||
{
|
||||
if (File.Exists(api64))
|
||||
{
|
||||
File.Delete(api64);
|
||||
if (installForm is not null)
|
||||
installForm.UpdateUser($"Deleted file: {Path.GetFileName(api64)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
File.Move(api64_o, api64);
|
||||
if (installForm is not null)
|
||||
installForm.UpdateUser($"Renamed file: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
if (File.Exists(cApi))
|
||||
{
|
||||
File.Delete(cApi);
|
||||
if (installForm is not null)
|
||||
installForm.UpdateUser($"Deleted file: {Path.GetFileName(cApi)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
});
|
||||
|
||||
internal static async Task InstallCreamAPI(string directory, ProgramSelection selection, InstallForm installForm = null) => await Task.Run(() =>
|
||||
{
|
||||
directory.GetApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string cApi);
|
||||
if (File.Exists(api) && !File.Exists(api_o))
|
||||
{
|
||||
File.Move(api, api_o);
|
||||
if (installForm is not null)
|
||||
installForm.UpdateUser($"Renamed file: {Path.GetFileName(api)} -> {Path.GetFileName(api_o)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
if (File.Exists(api_o))
|
||||
{
|
||||
Properties.Resources.API.Write(api);
|
||||
if (installForm is not null)
|
||||
installForm.UpdateUser($"Wrote resource to file: {Path.GetFileName(api)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
if (File.Exists(api64) && !File.Exists(api64_o))
|
||||
{
|
||||
File.Move(api64, api64_o);
|
||||
if (installForm is not null)
|
||||
installForm.UpdateUser($"Renamed file: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
if (File.Exists(api64_o))
|
||||
{
|
||||
Properties.Resources.API64.Write(api64);
|
||||
if (installForm is not null)
|
||||
installForm.UpdateUser($"Wrote resource to file: {Path.GetFileName(api64)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
if (installForm is not null)
|
||||
installForm.UpdateUser("Generating CreamAPI for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
|
||||
File.Create(cApi).Close();
|
||||
StreamWriter writer = new(cApi, true, Encoding.UTF8);
|
||||
writer.WriteLine("; " + Application.CompanyName + " v" + Application.ProductVersion);
|
||||
if (selection.SteamAppId > 0)
|
||||
WriteConfiguration(writer, selection.SteamAppId, selection.Name, selection.SelectedSteamDlc, installForm);
|
||||
foreach (Tuple<int, string, SortedList<int, (string name, string iconStaticId)>> extraAppDlc in selection.ExtraSteamAppIdDlc)
|
||||
WriteConfiguration(writer, extraAppDlc.Item1, extraAppDlc.Item2, extraAppDlc.Item3, installForm);
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
});
|
||||
|
||||
private async Task OperateFor(ProgramSelection selection)
|
||||
{
|
||||
UpdateProgress(0);
|
||||
|
@ -74,73 +156,12 @@ internal partial class InstallForm : CustomForm
|
|||
int cur = 0;
|
||||
foreach (string directory in selection.SteamApiDllDirectories)
|
||||
{
|
||||
await UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} CreamAPI for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
|
||||
UpdateUser($"{(Uninstalling ? "Uninstalling" : "Installing")} CreamAPI for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
|
||||
if (!Program.IsProgramRunningDialog(this, selection)) throw new OperationCanceledException();
|
||||
string api = directory + @"\steam_api.dll";
|
||||
string api_o = directory + @"\steam_api_o.dll";
|
||||
string api64 = directory + @"\steam_api64.dll";
|
||||
string api64_o = directory + @"\steam_api64_o.dll";
|
||||
string cApi = directory + @"\cream_api.ini";
|
||||
if (Uninstalling)
|
||||
{
|
||||
if (File.Exists(api_o))
|
||||
{
|
||||
if (File.Exists(api))
|
||||
{
|
||||
File.Delete(api);
|
||||
await UpdateUser($"Deleted file: {Path.GetFileName(api)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
File.Move(api_o, api);
|
||||
await UpdateUser($"Renamed file: {Path.GetFileName(api_o)} -> {Path.GetFileName(api)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
if (File.Exists(api64_o))
|
||||
{
|
||||
if (File.Exists(api64))
|
||||
{
|
||||
File.Delete(api64);
|
||||
await UpdateUser($"Deleted file: {Path.GetFileName(api64)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
File.Move(api64_o, api64);
|
||||
await UpdateUser($"Renamed file: {Path.GetFileName(api64_o)} -> {Path.GetFileName(api64)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
if (File.Exists(cApi))
|
||||
{
|
||||
File.Delete(cApi);
|
||||
await UpdateUser($"Deleted file: {Path.GetFileName(cApi)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
}
|
||||
await UninstallCreamAPI(directory, this);
|
||||
else
|
||||
{
|
||||
if (File.Exists(api) && !File.Exists(api_o))
|
||||
{
|
||||
File.Move(api, api_o);
|
||||
await UpdateUser($"Renamed file: {Path.GetFileName(api)} -> {Path.GetFileName(api_o)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
if (File.Exists(api_o))
|
||||
{
|
||||
Properties.Resources.API.Write(api);
|
||||
await UpdateUser($"Wrote resource to file: {Path.GetFileName(api)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
if (File.Exists(api64) && !File.Exists(api64_o))
|
||||
{
|
||||
File.Move(api64, api64_o);
|
||||
await UpdateUser($"Renamed file: {Path.GetFileName(api64)} -> {Path.GetFileName(api64_o)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
if (File.Exists(api64_o))
|
||||
{
|
||||
Properties.Resources.API64.Write(api64);
|
||||
await UpdateUser($"Wrote resource to file: {Path.GetFileName(api64)}", InstallationLog.Resource, info: false);
|
||||
}
|
||||
await UpdateUser("Generating CreamAPI for " + selection.Name + $" in directory \"{directory}\" . . . ", InstallationLog.Operation);
|
||||
File.Create(cApi).Close();
|
||||
StreamWriter writer = new(cApi, true, Encoding.UTF8);
|
||||
writer.WriteLine("; " + Application.CompanyName + " v" + Application.ProductVersion);
|
||||
if (selection.SteamAppId > 0) await WriteConfiguration(writer, selection.SteamAppId, selection.Name, selection.SelectedSteamDlc);
|
||||
foreach (Tuple<int, string, SortedList<int, (string name, string iconStaticId)>> extraAppDlc in selection.ExtraSteamAppIdDlc)
|
||||
await WriteConfiguration(writer, extraAppDlc.Item1, extraAppDlc.Item2, extraAppDlc.Item3);
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
}
|
||||
await InstallCreamAPI(directory, selection, this);
|
||||
UpdateProgress(++cur / count * 100);
|
||||
}
|
||||
UpdateProgress(100);
|
||||
|
@ -158,13 +179,13 @@ internal partial class InstallForm : CustomForm
|
|||
try
|
||||
{
|
||||
await OperateFor(selection);
|
||||
await UpdateUser($"Operation succeeded for {selection.Name}.", InstallationLog.Success);
|
||||
UpdateUser($"Operation succeeded for {selection.Name}.", InstallationLog.Success);
|
||||
selection.Enabled = false;
|
||||
disabledSelections.Add(selection);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
await UpdateUser($"Operation failed for {selection.Name}: " + exception.ToString(), InstallationLog.Error);
|
||||
UpdateUser($"Operation failed for {selection.Name}: " + exception.ToString(), InstallationLog.Error);
|
||||
}
|
||||
++CompleteOperationsCount;
|
||||
}
|
||||
|
@ -188,11 +209,11 @@ internal partial class InstallForm : CustomForm
|
|||
try
|
||||
{
|
||||
await Operate();
|
||||
await UpdateUser($"CreamAPI successfully {(Uninstalling ? "uninstalled" : "installed and generated")} for " + ProgramCount + " program(s).", InstallationLog.Success);
|
||||
UpdateUser($"CreamAPI successfully {(Uninstalling ? "uninstalled" : "installed and generated")} for " + ProgramCount + " program(s).", InstallationLog.Success);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
await UpdateUser($"CreamAPI {(Uninstalling ? "uninstallation" : "installation and/or generation")} failed: " + exception.ToString(), InstallationLog.Error);
|
||||
UpdateUser($"CreamAPI {(Uninstalling ? "uninstallation" : "installation and/or generation")} failed: " + exception.ToString(), InstallationLog.Error);
|
||||
retryButton.Enabled = true;
|
||||
}
|
||||
userProgressBar.Value = userProgressBar.Maximum;
|
||||
|
|
|
@ -12,6 +12,7 @@ using System.Windows.Forms;
|
|||
|
||||
using CreamInstaller.Classes;
|
||||
using CreamInstaller.Forms.Components;
|
||||
using CreamInstaller.Resources;
|
||||
|
||||
using Gameloop.Vdf.Linq;
|
||||
|
||||
|
@ -58,9 +59,13 @@ internal partial class SelectForm : CustomForm
|
|||
{
|
||||
List<string> dllDirectories = new();
|
||||
if (Program.Canceled || !Directory.Exists(gameDirectory)) return null;
|
||||
string api = gameDirectory + @"\steam_api.dll";
|
||||
string api64 = gameDirectory + @"\steam_api64.dll";
|
||||
if (File.Exists(api) || File.Exists(api64)) dllDirectories.Add(gameDirectory);
|
||||
gameDirectory.GetApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string cApi);
|
||||
if (File.Exists(api)
|
||||
|| File.Exists(api_o)
|
||||
|| File.Exists(api64)
|
||||
|| File.Exists(api64_o)
|
||||
|| File.Exists(cApi))
|
||||
dllDirectories.Add(gameDirectory);
|
||||
string[] directories = Directory.GetDirectories(gameDirectory);
|
||||
foreach (string _directory in directories)
|
||||
{
|
||||
|
@ -549,6 +554,56 @@ internal partial class SelectForm : CustomForm
|
|||
}
|
||||
if (selection is not null)
|
||||
{
|
||||
if (appId == 0)
|
||||
{
|
||||
nodeContextMenu.Items.Add(new ToolStripSeparator());
|
||||
nodeContextMenu.Items.Add(new ToolStripMenuItem("Repair", Image("Command Prompt"),
|
||||
new EventHandler(async (sender, e) =>
|
||||
{
|
||||
if (!Program.IsProgramRunningDialog(this, selection)) return;
|
||||
bool shouldReinstall = false;
|
||||
byte[] properApi = null;
|
||||
byte[] properApi64 = null;
|
||||
foreach (string directory in selection.SteamApiDllDirectories)
|
||||
{
|
||||
directory.GetApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string cApi);
|
||||
shouldReinstall = File.Exists(cApi);
|
||||
await InstallForm.UninstallCreamAPI(directory);
|
||||
if (properApi is null && File.Exists(api) && !FileResourceExtensions.Equals(Properties.Resources.API, api))
|
||||
properApi = File.ReadAllBytes(api);
|
||||
if (properApi64 is null && File.Exists(api64) && !FileResourceExtensions.Equals(Properties.Resources.API64, api64))
|
||||
properApi64 = File.ReadAllBytes(api64);
|
||||
}
|
||||
if (properApi is not null || properApi64 is not null)
|
||||
{
|
||||
bool neededRepair = false;
|
||||
foreach (string directory in selection.SteamApiDllDirectories)
|
||||
{
|
||||
directory.GetApiComponents(out string api, out string api_o, out string api64, out string api64_o, out string cApi);
|
||||
if (properApi is not null && FileResourceExtensions.Equals(Properties.Resources.API, api))
|
||||
{
|
||||
properApi.Write(api);
|
||||
neededRepair = true;
|
||||
}
|
||||
if (properApi64 is not null && FileResourceExtensions.Equals(Properties.Resources.API64, api64))
|
||||
{
|
||||
properApi64.Write(api64);
|
||||
neededRepair = true;
|
||||
}
|
||||
if (shouldReinstall)
|
||||
await InstallForm.InstallCreamAPI(directory, selection);
|
||||
}
|
||||
if (neededRepair)
|
||||
new DialogForm(this).Show("Paradox Launcher Repair", Icon, "Paradox Launcher successfully repaired!", "OK");
|
||||
else
|
||||
new DialogForm(this).Show("Paradox Launcher Repair", SystemIcons.Information, "Paradox Launcher does not need to be repaired.", "OK");
|
||||
}
|
||||
else
|
||||
new DialogForm(this).Show("Paradox Launcher Repair", SystemIcons.Error, "Paradox Launcher repair failed!"
|
||||
+ "\n\nAn original Steamworks API file could not be found."
|
||||
+ "\nYou must reinstall Paradox Launcher to fix this issue.", "OK");
|
||||
})));
|
||||
}
|
||||
nodeContextMenu.Items.Add(new ToolStripSeparator());
|
||||
nodeContextMenu.Items.Add(new ToolStripMenuItem("Open Root Directory", Image("File Explorer"),
|
||||
new EventHandler((sender, e) => Program.OpenDirectoryInFileExplorer(selection.RootDirectory))));
|
||||
|
|
|
@ -51,6 +51,15 @@ internal static class Program
|
|||
}
|
||||
}
|
||||
|
||||
internal static void GetApiComponents(this string directory, out string api, out string api_o, out string api64, out string api64_o, out string cApi)
|
||||
{
|
||||
api = directory + @"\steam_api.dll";
|
||||
api_o = directory + @"\steam_api_o.dll";
|
||||
api64 = directory + @"\steam_api64.dll";
|
||||
api64_o = directory + @"\steam_api64_o.dll";
|
||||
cApi = directory + @"\cream_api.ini";
|
||||
}
|
||||
|
||||
internal static bool IsGameBlocked(string name, string directory)
|
||||
{
|
||||
if (!BlockProtectedGames) return false;
|
||||
|
@ -86,6 +95,12 @@ internal static class Program
|
|||
mutex.Close();
|
||||
}
|
||||
|
||||
internal static Icon ToIcon(this Image image)
|
||||
{
|
||||
Bitmap dialogIconBitmap = new(image, new Size(image.Width, image.Height));
|
||||
return Icon.FromHandle(dialogIconBitmap.GetHicon());
|
||||
}
|
||||
|
||||
private static readonly string SteamAppImagesPath = "https://cdn.cloudflare.steamstatic.com/steamcommunity/public/images/apps/";
|
||||
internal static async Task<Image> GetSteamIcon(int steamAppId, string iconStaticId) => await GetImageFromUrl(SteamAppImagesPath + $"/{steamAppId}/{iconStaticId}.jpg");
|
||||
internal static async Task<Image> GetSteamClientIcon(int steamAppId, string clientIconStaticId) => await GetImageFromUrl(SteamAppImagesPath + $"/{steamAppId}/{clientIconStaticId}.ico");
|
||||
|
|
|
@ -9,4 +9,15 @@ internal static class FileResourceExtensions
|
|||
using FileStream file = new(filePath, FileMode.Create, FileAccess.Write);
|
||||
file.Write(resource);
|
||||
}
|
||||
|
||||
internal static bool Equals(byte[] resource, string filePath)
|
||||
{
|
||||
byte[] file = File.ReadAllBytes(filePath);
|
||||
if (resource.Length != file.Length)
|
||||
return false;
|
||||
for (int i = 0; i < resource.Length; i++)
|
||||
if (resource[i] != file[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue