From a634351c9d8f9ec1137910b89edb44bc2e43927b Mon Sep 17 00:00:00 2001 From: pizzaboxer <41478239+pizzaboxer@users.noreply.github.com> Date: Mon, 13 Feb 2023 22:05:10 +0000 Subject: [PATCH] Add logging saves to bloxstrap folder if installed, temp local appdata folder if not installed or uninstalling --- Bloxstrap/App.xaml.cs | 21 +++-- Bloxstrap/Bootstrapper.cs | 76 ++++++++++++------- Bloxstrap/Helpers/Directories.cs | 1 + .../Integrations/DiscordRichPresence.cs | 26 +++++-- .../Helpers/Integrations/RbxFpsUnlocker.cs | 2 +- Bloxstrap/Helpers/Integrations/ReShade.cs | 28 +++---- Bloxstrap/Helpers/JsonManager.cs | 14 ++-- Bloxstrap/Helpers/Logger.cs | 50 ++++++++++++ Bloxstrap/Helpers/Protocol.cs | 5 +- Bloxstrap/Views/Pages/AboutPage.xaml | 4 +- Bloxstrap/Views/Pages/BootstrapperPage.xaml | 2 +- Bloxstrap/Views/Pages/ReShadeHelpPage.xaml | 12 ++- 12 files changed, 175 insertions(+), 66 deletions(-) create mode 100644 Bloxstrap/Helpers/Logger.cs diff --git a/Bloxstrap/App.xaml.cs b/Bloxstrap/App.xaml.cs index 9620c2b..abfb013 100644 --- a/Bloxstrap/App.xaml.cs +++ b/Bloxstrap/App.xaml.cs @@ -30,7 +30,7 @@ namespace Bloxstrap public static string BaseDirectory = null!; public static bool ShouldSaveConfigs { get; set; } = false; public static bool IsSetupComplete { get; set; } = true; - public static bool IsFirstRun { get; private set; } = false; + public static bool IsFirstRun { get; private set; } = true; public static bool IsQuiet { get; private set; } = false; public static bool IsUninstall { get; private set; } = false; public static bool IsNoLaunch { get; private set; } = false; @@ -40,6 +40,8 @@ namespace Bloxstrap public static string Version = Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2]; + // singletons + public static Logger Logger { get; private set; } = null!; public static readonly JsonManager Settings = new(); public static readonly JsonManager State = new(); public static readonly HttpClient HttpClient = new(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.All }); @@ -55,7 +57,7 @@ namespace Bloxstrap public static void Terminate(int code = Bootstrapper.ERROR_SUCCESS) { - Debug.WriteLine($"[App] Terminating with exit code {code}"); + Logger.WriteLine($"[App::Terminate] Terminating with exit code {code}"); Settings.Save(); State.Save(); Environment.Exit(code); @@ -94,7 +96,6 @@ namespace Bloxstrap if (registryKey is null) { - IsFirstRun = true; BaseDirectory = Path.Combine(Directories.LocalAppData, ProjectName); if (!IsQuiet) @@ -105,6 +106,7 @@ namespace Bloxstrap } else { + IsFirstRun = false; BaseDirectory = (string)registryKey.GetValue("InstallLocation")!; registryKey.Close(); } @@ -115,6 +117,10 @@ namespace Bloxstrap Directories.Initialize(BaseDirectory); + string logdir = IsFirstRun || IsUninstall ? Path.Combine(Directories.LocalAppData, "Temp") : Path.Combine(Directories.Base, "Logs"); + string timestamp = DateTime.UtcNow.ToString("yyyyMMdd'T'HHmmss'Z'"); + Logger = new(Path.Combine(logdir, $"{ProjectName}_{timestamp}.log")); + // we shouldn't save settings on the first run until the first installation is finished, // just in case the user decides to cancel the install if (!IsFirstRun) @@ -182,16 +188,19 @@ namespace Bloxstrap Task bootstrapperTask = Task.Run(() => bootstrapper.Run()).ContinueWith(t => { - // TODO: add error logging - Debug.WriteLine("[App] Bootstrapper task has finished"); + Logger.WriteLine("[App::OnStartup] Bootstrapper task has finished"); if (t.Exception is null) return; + Logger.WriteLine("[App::OnStartup] An exception occurred when running the bootstrapper"); + Logger.WriteLine($"[App::OnStartup] {t.Exception}"); + #if DEBUG throw t.Exception; #else - dialog?.ShowError(t.Exception.ToString()); + var exception = t.Exception.InnerExceptions.Count >= 1 ? t.Exception.InnerExceptions[0] : t.Exception; + dialog?.ShowError($"{exception.GetType()}: {exception.Message}"); #endif }); diff --git a/Bloxstrap/Bootstrapper.cs b/Bloxstrap/Bootstrapper.cs index 93aecc9..bd1cc7c 100644 --- a/Bloxstrap/Bootstrapper.cs +++ b/Bloxstrap/Bootstrapper.cs @@ -91,7 +91,7 @@ namespace Bloxstrap private void SetStatus(string message) { - Debug.WriteLine($"[Bootstrapper] {message}"); + App.Logger.WriteLine($"[Bootstrapper::SetStatus] {message}"); if (Dialog is not null) Dialog.Message = message; @@ -99,6 +99,8 @@ namespace Bloxstrap public async Task Run() { + App.Logger.WriteLine("[Bootstrapper::Run] Running bootstrapper"); + if (App.IsUninstall) { Uninstall(); @@ -142,10 +144,15 @@ namespace Bloxstrap { string currentVersion = $"{App.ProjectName} v{App.Version}"; + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Checking for {App.ProjectName} updates..."); + var releaseInfo = await Utilities.GetJson($"https://api.github.com/repos/{App.ProjectRepository}/releases/latest"); if (releaseInfo?.Assets is null || currentVersion == releaseInfo.Name) + { + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] No updates found"); return; + } SetStatus($"Getting the latest {App.ProjectName}..."); @@ -155,7 +162,7 @@ namespace Bloxstrap Directory.CreateDirectory(Directories.Updates); - Debug.WriteLine($"Downloading {releaseInfo.Name}..."); + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Downloading {releaseInfo.Name}..."); if (!File.Exists(downloadLocation)) { @@ -165,7 +172,7 @@ namespace Bloxstrap await response.Content.CopyToAsync(fileStream); } - Debug.WriteLine($"Starting {releaseInfo.Name}..."); + App.Logger.WriteLine($"[Bootstrapper::CheckForUpdates] Starting {releaseInfo.Name}..."); ProcessStartInfo startInfo = new() { @@ -255,8 +262,10 @@ namespace Bloxstrap return; } - if (App.Settings.Prop.RFUEnabled && Process.GetProcessesByName("rbxfpsunlocker").Length == 0) - { + if (App.Settings.Prop.RFUEnabled && Process.GetProcessesByName("rbxfpsunlocker").Length == 0) + { + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using rbxfpsunlocker"); + ProcessStartInfo startInfo = new() { WorkingDirectory = Path.Combine(Directories.Integrations, "rbxfpsunlocker"), @@ -269,8 +278,16 @@ namespace Bloxstrap shouldWait = true; } + if (App.Settings.Prop.UseDiscordRichPresence) + { + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Using Discord Rich Presence"); + richPresence = new DiscordRichPresence(); + shouldWait = true; + } + if (App.Settings.Prop.MultiInstanceLaunching) { + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Creating singleton mutex"); // this might be a bit problematic since this mutex will be released when the first launched instance is closed... singletonMutex = new Mutex(true, "ROBLOX_singletonMutex"); shouldWait = true; @@ -278,25 +295,21 @@ namespace Bloxstrap // event fired, wait for 3 seconds then close await Task.Delay(3000); + Dialog?.CloseBootstrapper(); - if (App.Settings.Prop.UseDiscordRichPresence) - { - richPresence = new DiscordRichPresence(); - richPresence.MonitorGameActivity(); - shouldWait = true; - } - + // keep bloxstrap open in the background if needed if (!shouldWait) return; - // keep bloxstrap open in the background - Dialog?.CloseBootstrapper(); + richPresence?.MonitorGameActivity(); + + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Waiting for Roblox to close"); await gameClient.WaitForExitAsync(); richPresence?.Dispose(); - if (App.Settings.Prop.RFUAutoclose && rbxFpsUnlocker is not null) - rbxFpsUnlocker.Kill(); + if (App.Settings.Prop.RFUAutoclose) + rbxFpsUnlocker?.Kill(); } public void CancelInstall() @@ -307,6 +320,8 @@ namespace Bloxstrap return; } + App.Logger.WriteLine("[Bootstrapper::CancelInstall] Cancelling install..."); + _cancelTokenSource.Cancel(); _cancelFired = true; @@ -320,8 +335,8 @@ namespace Bloxstrap } catch (Exception e) { - Debug.WriteLine("[Bootstrapper} Could not fully clean up installation!"); - Debug.WriteLine(e); + App.Logger.WriteLine("[Bootstrapper::CancelInstall] Could not fully clean up installation!"); + App.Logger.WriteLine($"[Bootstrapper::CancelInstall] {e}"); } App.Terminate(ERROR_INSTALL_USEREXIT); @@ -371,10 +386,14 @@ namespace Bloxstrap uninstallKey.SetValue("URLInfoAbout", $"https://github.com/{App.ProjectRepository}"); uninstallKey.SetValue("URLUpdateInfo", $"https://github.com/{App.ProjectRepository}/releases/latest"); uninstallKey.Close(); + + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Registered application version"); } public static void CheckInstall() { + App.Logger.WriteLine("[Bootstrapper::StartRoblox] Checking install"); + // check if launch uri is set to our bootstrapper // this doesn't go under register, so we check every launch // just in case the stock bootstrapper changes it back @@ -470,7 +489,7 @@ namespace Bloxstrap } catch (Exception e) { - Debug.WriteLine($"Could not fully uninstall! ({e})"); + App.Logger.WriteLine($"Could not fully uninstall! ({e})"); } Dialog?.ShowSuccess($"{App.ProjectName} has succesfully uninstalled"); @@ -563,7 +582,10 @@ namespace Bloxstrap foreach (string filename in Directory.GetFiles(Directories.Downloads)) { if (!_versionPackageManifest.Exists(package => filename.Contains(package.Signature))) + { + App.Logger.WriteLine($"Deleting unused package {filename}"); File.Delete(filename); + } } string oldVersionFolder = Path.Combine(Directories.Versions, App.State.Prop.VersionGuid); @@ -716,12 +738,12 @@ namespace Bloxstrap string calculatedMD5 = Utilities.MD5File(packageLocation); if (calculatedMD5 != package.Signature) { - Debug.WriteLine($"{package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading..."); + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is corrupted ({calculatedMD5} != {package.Signature})! Deleting and re-downloading..."); file.Delete(); } else { - Debug.WriteLine($"{package.Name} is already downloaded, skipping..."); + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] {package.Name} is already downloaded, skipping..."); _totalDownloadedBytes += package.PackedSize; UpdateProgressbar(); return; @@ -732,7 +754,7 @@ namespace Bloxstrap // let's cheat! if the stock bootstrapper already previously downloaded the file, // then we can just copy the one from there - Debug.WriteLine($"Found existing version of {package.Name} ({robloxPackageLocation})! Copying to Downloads folder..."); + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Found existing version of {package.Name} ({robloxPackageLocation})! Copying to Downloads folder..."); File.Copy(robloxPackageLocation, packageLocation); _totalDownloadedBytes += package.PackedSize; UpdateProgressbar(); @@ -741,7 +763,7 @@ namespace Bloxstrap if (!File.Exists(packageLocation)) { - Debug.WriteLine($"Downloading {package.Name} ({package.Signature})..."); + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Downloading {package.Name} ({package.Signature})..."); { var response = await App.HttpClient.GetAsync(packageUrl, HttpCompletionOption.ResponseHeadersRead, _cancelTokenSource.Token); @@ -771,7 +793,7 @@ namespace Bloxstrap } } - Debug.WriteLine($"Finished downloading {package.Name}!"); + App.Logger.WriteLine($"[Bootstrapper::DownloadPackage] Finished downloading {package.Name}!"); } } @@ -784,7 +806,7 @@ namespace Bloxstrap string packageFolder = Path.Combine(_versionFolder, PackageDirectories[package.Name]); string extractPath; - Debug.WriteLine($"Extracting {package.Name} to {packageFolder}..."); + App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Extracting {package.Name} to {packageFolder}..."); using (ZipArchive archive = await Task.Run(() => ZipFile.OpenRead(packageLocation))) { @@ -798,7 +820,7 @@ namespace Bloxstrap extractPath = Path.Combine(packageFolder, entry.FullName); - //Debug.WriteLine($"[{package.Name}] Writing {extractPath}..."); + //App.Logger.WriteLine($"[{package.Name}] Writing {extractPath}..."); string? directory = Path.GetDirectoryName(extractPath); @@ -811,7 +833,7 @@ namespace Bloxstrap } } - Debug.WriteLine($"Finished extracting {package.Name}"); + App.Logger.WriteLine($"[Bootstrapper::ExtractPackage] Finished extracting {package.Name}"); _packagesExtracted += 1; } diff --git a/Bloxstrap/Helpers/Directories.cs b/Bloxstrap/Helpers/Directories.cs index d014107..87005bc 100644 --- a/Bloxstrap/Helpers/Directories.cs +++ b/Bloxstrap/Helpers/Directories.cs @@ -7,6 +7,7 @@ namespace Bloxstrap.Helpers { // note that these are directories that aren't tethered to the basedirectory // so these can safely be called before initialization + public static string UserProfile => Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); public static string LocalAppData => Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); public static string Desktop => Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); public static string StartMenu => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Programs", App.ProjectName); diff --git a/Bloxstrap/Helpers/Integrations/DiscordRichPresence.cs b/Bloxstrap/Helpers/Integrations/DiscordRichPresence.cs index 52c50f9..23362ff 100644 --- a/Bloxstrap/Helpers/Integrations/DiscordRichPresence.cs +++ b/Bloxstrap/Helpers/Integrations/DiscordRichPresence.cs @@ -32,12 +32,28 @@ namespace Bloxstrap.Helpers.Integrations public DiscordRichPresence() { + RichPresence.OnReady += (_, e) => + App.Logger.WriteLine($"[DiscordRichPresence::DiscordRichPresence] Received ready from user {e.User.Username} ({e.User.ID})"); + + RichPresence.OnPresenceUpdate += (_, e) => + App.Logger.WriteLine("[DiscordRichPresence::DiscordRichPresence] Updated presence"); + + RichPresence.OnConnectionEstablished += (_, e) => + App.Logger.WriteLine("[DiscordRichPresence::DiscordRichPresence] Established connection with Discord RPC!"); + + //spams log as it tries to connect every ~15 sec when discord is closed so not now + //RichPresence.OnConnectionFailed += (_, e) => + // App.Logger.WriteLine("[DiscordRichPresence::DiscordRichPresence] Failed to establish connection with Discord RPC!"); + + RichPresence.OnClose += (_, e) => + App.Logger.WriteLine($"[DiscordRichPresence::DiscordRichPresence] Lost connection to Discord RPC - {e.Reason} ({e.Code})"); + RichPresence.Initialize(); } private async Task ExamineLogEntry(string entry) { - Debug.WriteLine(entry); + // App.Logger.WriteLine(entry); if (entry.Contains(GameJoiningEntry) && !ActivityInGame && ActivityPlaceId == 0) { @@ -51,7 +67,7 @@ namespace Bloxstrap.Helpers.Integrations ActivityJobId = match.Groups[1].Value; ActivityMachineAddress = match.Groups[3].Value; - Debug.WriteLine($"[DiscordRichPresence] Joining Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})"); + App.Logger.WriteLine($"[DiscordRichPresence::ExamineLogEntry] Joining Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})"); } else if (entry.Contains(GameJoinedEntry) && !ActivityInGame && ActivityPlaceId != 0) { @@ -60,14 +76,14 @@ namespace Bloxstrap.Helpers.Integrations if (match.Groups.Count != 3 || match.Groups[1].Value != ActivityMachineAddress) return; - Debug.WriteLine($"[DiscordRichPresence] Joined Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})"); + App.Logger.WriteLine($"[DiscordRichPresence::ExamineLogEntry] Joined Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})"); ActivityInGame = true; await SetPresence(); } else if (entry.Contains(GameDisconnectedEntry) && ActivityInGame && ActivityPlaceId != 0) { - Debug.WriteLine($"[DiscordRichPresence] Disconnected from Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})"); + App.Logger.WriteLine($"[DiscordRichPresence::ExamineLogEntry] Disconnected from Game ({ActivityPlaceId}/{ActivityJobId}/{ActivityMachineAddress})"); ActivityInGame = false; ActivityPlaceId = 0; @@ -136,7 +152,7 @@ namespace Bloxstrap.Helpers.Integrations } else { - //Debug.WriteLine(log); + //App.Logger.WriteLine(log); await ExamineLogEntry(log); } } diff --git a/Bloxstrap/Helpers/Integrations/RbxFpsUnlocker.cs b/Bloxstrap/Helpers/Integrations/RbxFpsUnlocker.cs index 36f640e..b75f2d0 100644 --- a/Bloxstrap/Helpers/Integrations/RbxFpsUnlocker.cs +++ b/Bloxstrap/Helpers/Integrations/RbxFpsUnlocker.cs @@ -90,7 +90,7 @@ namespace Bloxstrap.Helpers.Integrations File.Delete(fileLocation); } - Debug.WriteLine("Installing/Updating rbxfpsunlocker..."); + App.Logger.WriteLine("[RbxFpsUnlocker::CheckInstall] Installing/Updating rbxfpsunlocker..."); { byte[] bytes = await App.HttpClient.GetByteArrayAsync(downloadUrl); diff --git a/Bloxstrap/Helpers/Integrations/ReShade.cs b/Bloxstrap/Helpers/Integrations/ReShade.cs index 284dc89..ddaf95f 100644 --- a/Bloxstrap/Helpers/Integrations/ReShade.cs +++ b/Bloxstrap/Helpers/Integrations/ReShade.cs @@ -69,7 +69,7 @@ namespace Bloxstrap.Helpers.Integrations public static async Task DownloadConfig() { - Debug.WriteLine("[ReShade] Downloading/Upgrading config file..."); + App.Logger.WriteLine("[ReShade::DownloadConfig] Downloading/Upgrading config file..."); { byte[] bytes = await App.HttpClient.GetByteArrayAsync($"{BaseUrl}/config.zip"); @@ -117,7 +117,7 @@ namespace Bloxstrap.Helpers.Integrations public static void SynchronizeConfigFile() { - Debug.WriteLine($"[ReShade] Synchronizing configuration file..."); + App.Logger.WriteLine($"[ReShade::SynchronizeConfigFile] Synchronizing configuration file..."); // yeah, this is going to be a bit of a pain // keep in mind the config file is going to be in two places: the mod folder and the version folder @@ -134,21 +134,21 @@ namespace Bloxstrap.Helpers.Integrations // we shouldn't be here if the mod config doesn't already exist if (!File.Exists(modFolderConfigPath)) { - Debug.WriteLine($"[ReShade] ReShade.ini in modifications folder does not exist, aborting sync"); + App.Logger.WriteLine($"[ReShade::SynchronizeConfigFile] ReShade.ini in modifications folder does not exist, aborting sync"); return; } // copy to the version folder if it doesn't already exist there if (!File.Exists(versionFolderConfigPath)) { - Debug.WriteLine($"[ReShade] ReShade.ini in version folder does not exist, synchronized with modifications folder"); + App.Logger.WriteLine($"[ReShade::SynchronizeConfigFile] ReShade.ini in version folder does not exist, synchronized with modifications folder"); File.Copy(modFolderConfigPath, versionFolderConfigPath); } // if both the mod and version configs match, then we don't need to do anything if (Utilities.MD5File(modFolderConfigPath) == Utilities.MD5File(versionFolderConfigPath)) { - Debug.WriteLine($"[ReShade] ReShade.ini in version and modifications folder match"); + App.Logger.WriteLine($"[ReShade::SynchronizeConfigFile] ReShade.ini in version and modifications folder match"); return; } @@ -158,13 +158,13 @@ namespace Bloxstrap.Helpers.Integrations if (modFolderConfigFile.LastWriteTime > versionFolderConfigFile.LastWriteTime) { // overwrite version config if mod config was modified most recently - Debug.WriteLine($"[ReShade] ReShade.ini in version folder is older, synchronized with modifications folder"); + App.Logger.WriteLine($"[ReShade::SynchronizeConfigFile] ReShade.ini in version folder is older, synchronized with modifications folder"); File.Copy(modFolderConfigPath, versionFolderConfigPath, true); } else if (versionFolderConfigFile.LastWriteTime > modFolderConfigFile.LastWriteTime) { // overwrite mod config if version config was modified most recently - Debug.WriteLine($"[ReShade] ReShade.ini in modifications folder is older, synchronized with version folder"); + App.Logger.WriteLine($"[ReShade::SynchronizeConfigFile] ReShade.ini in modifications folder is older, synchronized with version folder"); File.Copy(versionFolderConfigPath, modFolderConfigPath, true); } } @@ -177,7 +177,7 @@ namespace Bloxstrap.Helpers.Integrations if (Directory.Exists(Path.Combine(ShadersFolder, name))) return; - Debug.WriteLine($"[ReShade] Downloading shaders for {name}"); + App.Logger.WriteLine($"[ReShade::DownloadShaders] Downloading shaders for {name}"); { byte[] bytes = await App.HttpClient.GetByteArrayAsync(downloadUrl); @@ -238,7 +238,7 @@ namespace Bloxstrap.Helpers.Integrations public static void DeleteShaders(string name) { - Debug.WriteLine($"[ReShade] Deleting shaders for {name}"); + App.Logger.WriteLine($"[ReShade::DeleteShaders] Deleting shaders for {name}"); string shadersPath = Path.Combine(ShadersFolder, name); string texturesPath = Path.Combine(TexturesFolder, name); @@ -276,7 +276,7 @@ namespace Bloxstrap.Helpers.Integrations public static async Task InstallExtraviPresets() { - Debug.WriteLine("[ReShade] Installing Extravi's presets..."); + App.Logger.WriteLine("[ReShade::InstallExtraviPresets] Installing Extravi's presets..."); foreach (string name in ExtraviPresetsShaders) await DownloadShaders(name); @@ -303,7 +303,7 @@ namespace Bloxstrap.Helpers.Integrations if (!Directory.Exists(PresetsFolder)) return; - Debug.WriteLine("[ReShade] Uninstalling Extravi's presets..."); + App.Logger.WriteLine("[ReShade::UninstallExtraviPresets] Uninstalling Extravi's presets..."); FileInfo[] presets = new DirectoryInfo(PresetsFolder).GetFiles(); @@ -319,7 +319,7 @@ namespace Bloxstrap.Helpers.Integrations public static async Task CheckModifications() { - Debug.WriteLine("[ReShade] Checking ReShade modifications... "); + App.Logger.WriteLine("[ReShade::CheckModifications] Checking ReShade modifications... "); string injectorLocation = Path.Combine(Directories.Modifications, "dxgi.dll"); @@ -332,7 +332,7 @@ namespace Bloxstrap.Helpers.Integrations if (!App.Settings.Prop.UseReShade) { - Debug.WriteLine("[ReShade] Uninstalling ReShade..."); + App.Logger.WriteLine("[ReShade::CheckModifications] Uninstalling ReShade..."); // delete any stock config files File.Delete(injectorLocation); @@ -380,7 +380,7 @@ namespace Bloxstrap.Helpers.Integrations if (shouldFetchReShade) { - Debug.WriteLine("[ReShade] Installing/Upgrading ReShade..."); + App.Logger.WriteLine("[ReShade::CheckModifications] Installing/Upgrading ReShade..."); { byte[] bytes = await App.HttpClient.GetByteArrayAsync($"{BaseUrl}/dxgi.zip"); diff --git a/Bloxstrap/Helpers/JsonManager.cs b/Bloxstrap/Helpers/JsonManager.cs index 1389510..fed021f 100644 --- a/Bloxstrap/Helpers/JsonManager.cs +++ b/Bloxstrap/Helpers/JsonManager.cs @@ -25,42 +25,42 @@ namespace Bloxstrap.Helpers //if (String.IsNullOrEmpty(FileLocation)) // throw new ArgumentNullException("No FileLocation has been set"); - Debug.WriteLine($"[JsonManager<{typeof(T).Name}>] Loading JSON from {FileLocation}..."); + App.Logger.WriteLine($"[JsonManager<{typeof(T).Name}>::Load] Loading JSON from {FileLocation}..."); try { T? settings = JsonSerializer.Deserialize(File.ReadAllText(FileLocation)); Prop = settings ?? throw new ArgumentNullException("Deserialization returned null"); - Debug.WriteLine($"[JsonManager<{typeof(T).Name}>] JSON loaded successfully!"); + App.Logger.WriteLine($"[JsonManager<{typeof(T).Name}>::Load] JSON loaded successfully!"); } catch (Exception ex) { - Debug.WriteLine($"[JsonManager<{typeof(T).Name}>] Failed to load JSON! ({ex.Message})"); + App.Logger.WriteLine($"[JsonManager<{typeof(T).Name}>::Load] Failed to load JSON! ({ex.Message})"); } } public void Save() { - Debug.WriteLine($"[JsonManager<{typeof(T).Name}>] Attempting to save JSON to {FileLocation}..."); + App.Logger.WriteLine($"[JsonManager<{typeof(T).Name}>::Save] Attempting to save JSON to {FileLocation}..."); //if (!ShouldSave || String.IsNullOrEmpty(FileLocation)) //{ - // Debug.WriteLine($"[JsonManager<{typeof(T).Name}>] Aborted save (ShouldSave set to false or FileLocation not set)"); + // App.Logger.WriteLine($"[JsonManager<{typeof(T).Name}>] Aborted save (ShouldSave set to false or FileLocation not set)"); // return; //} //if (!ShouldSave) if (!App.ShouldSaveConfigs) { - Debug.WriteLine($"[JsonManager<{typeof(T).Name}>] Aborted save (ShouldSave set to false)"); + App.Logger.WriteLine($"[JsonManager<{typeof(T).Name}>::Save] Aborted save (ShouldSave set to false)"); return; } string json = JsonSerializer.Serialize(Prop, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(FileLocation, json); - Debug.WriteLine($"[JsonManager<{typeof(T).Name}>] JSON saved!"); + App.Logger.WriteLine($"[JsonManager<{typeof(T).Name}>::Save] JSON saved!"); } } } diff --git a/Bloxstrap/Helpers/Logger.cs b/Bloxstrap/Helpers/Logger.cs new file mode 100644 index 0000000..7d51523 --- /dev/null +++ b/Bloxstrap/Helpers/Logger.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Printing; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Bloxstrap.Helpers +{ + // https://stackoverflow.com/a/53873141/11852173 + public class Logger + { + private readonly SemaphoreSlim _semaphore = new(1, 1); + private readonly FileStream _filestream; + + public Logger(string filename) + { + string? directory = Path.GetDirectoryName(filename); + + if (directory is not null) + Directory.CreateDirectory(directory); + + _filestream = File.Open(filename, FileMode.Create, FileAccess.Write, FileShare.Read); + WriteLine($"[Logger::Logger] {App.ProjectName} v{App.Version} - Initialized at {filename}"); + } + + public async void WriteLine(string message) + { + string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ss'Z'"); + string conout = $"{timestamp} {message}"; + byte[] fileout = Encoding.Unicode.GetBytes($"{conout.Replace(Directories.UserProfile, "")}\r\n"); + + Debug.WriteLine(conout); + + try + { + await _semaphore.WaitAsync(); + await _filestream.WriteAsync(fileout); + await _filestream.FlushAsync(); + } + finally + { + _semaphore.Release(); + } + } + } +} diff --git a/Bloxstrap/Helpers/Protocol.cs b/Bloxstrap/Helpers/Protocol.cs index aada861..8387649 100644 --- a/Bloxstrap/Helpers/Protocol.cs +++ b/Bloxstrap/Helpers/Protocol.cs @@ -61,7 +61,10 @@ namespace Bloxstrap.Helpers ); if (result == MessageBoxResult.Yes) + { + App.Logger.WriteLine($"[Protocol::ParseUri] Changed Roblox build channel from {App.Settings.Prop.Channel} to {val}"); App.Settings.Prop.Channel = val; + } } // we'll set the arg when launching @@ -106,7 +109,7 @@ namespace Bloxstrap.Helpers } catch (Exception e) { - Debug.WriteLine($"Failed to unregister {key}: {e}"); + App.Logger.WriteLine($"[Protocol::Unregister] Failed to unregister {key}: {e}"); } } } diff --git a/Bloxstrap/Views/Pages/AboutPage.xaml b/Bloxstrap/Views/Pages/AboutPage.xaml index b2c00df..5e48c64 100644 --- a/Bloxstrap/Views/Pages/AboutPage.xaml +++ b/Bloxstrap/Views/Pages/AboutPage.xaml @@ -5,7 +5,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" mc:Ignorable="d" - d:DesignHeight="450" d:DesignWidth="800" + d:DesignHeight="700" d:DesignWidth="800" Title="AboutPage" Scrollable="True"> @@ -18,7 +18,7 @@ - + diff --git a/Bloxstrap/Views/Pages/BootstrapperPage.xaml b/Bloxstrap/Views/Pages/BootstrapperPage.xaml index 136f65e..eb04f74 100644 --- a/Bloxstrap/Views/Pages/BootstrapperPage.xaml +++ b/Bloxstrap/Views/Pages/BootstrapperPage.xaml @@ -11,7 +11,7 @@ Scrollable="True"> - + diff --git a/Bloxstrap/Views/Pages/ReShadeHelpPage.xaml b/Bloxstrap/Views/Pages/ReShadeHelpPage.xaml index 000c88d..022ed44 100644 --- a/Bloxstrap/Views/Pages/ReShadeHelpPage.xaml +++ b/Bloxstrap/Views/Pages/ReShadeHelpPage.xaml @@ -33,10 +33,18 @@ - + + If you're using a laptop keyboard, you may have to hold down the Fn key when pressing F6. + + + Any screenshots you take are saved to your pictures folder. + - + + + +