From 9b2d9707a93a67e13b20d681b071d762e0f951af Mon Sep 17 00:00:00 2001 From: rjindael Date: Wed, 2 Aug 2023 02:15:22 -0700 Subject: [PATCH] feat/chore: shortcuts, additional refactoring --- Kiseki.Launcher.Windows/Bootstrapper.cs | 75 ++++++++++++------- .../Kiseki.Launcher.Windows.csproj | 5 ++ .../{Directories.cs => Paths.cs} | 4 +- Kiseki.Launcher.Windows/Program.cs | 6 +- Kiseki.Launcher.Windows/Protocol.cs | 2 +- Kiseki.Launcher.Windows/Win32.cs | 9 --- 6 files changed, 61 insertions(+), 40 deletions(-) rename Kiseki.Launcher.Windows/{Directories.cs => Paths.cs} (79%) diff --git a/Kiseki.Launcher.Windows/Bootstrapper.cs b/Kiseki.Launcher.Windows/Bootstrapper.cs index e7e7946..d3ad921 100644 --- a/Kiseki.Launcher.Windows/Bootstrapper.cs +++ b/Kiseki.Launcher.Windows/Bootstrapper.cs @@ -5,6 +5,8 @@ using System.Reflection; using Microsoft.Win32; +using Syroot.Windows.IO; + public class Bootstrapper : Interfaces.IBootstrapper { public readonly static string Version = Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2]; @@ -88,16 +90,30 @@ public class Bootstrapper : Interfaces.IBootstrapper Protocol.Unregister(); Register(); - Directory.CreateDirectory(Directories.Base); - Directory.CreateDirectory(Directories.Versions); - Directory.CreateDirectory(Directories.Logs); + // Create paths + Directory.CreateDirectory(Paths.Base); + Directory.CreateDirectory(Paths.Versions); + Directory.CreateDirectory(Paths.Logs); - if (!File.Exists(Directories.Application)) - File.Copy(Application.ExecutablePath, Directories.Application, true); + // Copy ourselves + if (!File.Exists(Paths.Application)) + File.Copy(Application.ExecutablePath, Paths.Application, true); + // Register us and our protocol handler system-wide Register(); Protocol.Register(); + // Create shortcuts + if (File.Exists(Path.Combine(Paths.StartMenu, $"{Constants.PROJECT_NAME}.lnk"))) + File.Delete(Path.Combine(Paths.StartMenu, $"{Constants.PROJECT_NAME}.lnk")); + + if (File.Exists(Path.Combine(Paths.Desktop, $"{Constants.PROJECT_NAME}.lnk"))) + File.Delete(Path.Combine(Paths.Desktop, $"{Constants.PROJECT_NAME}.lnk")); + + ShellLink.Shortcut.CreateShortcut(Paths.Application, "", Paths.Application, 0).WriteToFile(Path.Combine(Paths.StartMenu, $"{Constants.PROJECT_NAME}.lnk")); + ShellLink.Shortcut.CreateShortcut(Paths.Application, "", Paths.Application, 0).WriteToFile(Path.Combine(Paths.Desktop, $"{Constants.PROJECT_NAME}.lnk")); + + // We're finished MessageBox.Show($"Sucessfully installed {Constants.PROJECT_NAME}!", Constants.PROJECT_NAME, MessageBoxButtons.OK, MessageBoxIcon.Information); Environment.Exit((int)Win32.ErrorCode.ERROR_SUCCESS); @@ -133,14 +149,21 @@ public class Bootstrapper : Interfaces.IBootstrapper } // Delete all files - if (Directory.Exists(Directories.Logs)) - Directory.Delete(Directories.Logs, true); + if (Directory.Exists(Paths.Logs)) + Directory.Delete(Paths.Logs, true); - if (Directory.Exists(Directories.Versions)) - Directory.Delete(Directories.Versions, true); + if (Directory.Exists(Paths.Versions)) + Directory.Delete(Paths.Versions, true); - if (File.Exists(Directories.License)) - File.Delete(Directories.License); + if (File.Exists(Paths.License)) + File.Delete(Paths.License); + + // Delete our shortcuts + if (File.Exists(Path.Combine(Paths.StartMenu, $"{Constants.PROJECT_NAME}.lnk"))) + File.Delete(Path.Combine(Paths.StartMenu, $"{Constants.PROJECT_NAME}.lnk")); + + if (File.Exists(Path.Combine(Paths.Desktop, $"{Constants.PROJECT_NAME}.lnk"))) + File.Delete(Path.Combine(Paths.Desktop, $"{Constants.PROJECT_NAME}.lnk")); // Cleanup our registry entries Unregister(); @@ -149,12 +172,12 @@ public class Bootstrapper : Interfaces.IBootstrapper answer = quiet ? DialogResult.OK : MessageBox.Show($"Sucessfully uninstalled {Constants.PROJECT_NAME}!", Constants.PROJECT_NAME, MessageBoxButtons.OK, MessageBoxIcon.Information); if (answer == DialogResult.OK || answer == DialogResult.Cancel) { - string command = $"del /Q \"{Directories.Application}\""; + string command = $"del /Q \"{Paths.Application}\""; - if (Directory.GetFiles(Directories.Base, "*", SearchOption.AllDirectories).Length == 1) + if (Directory.GetFiles(Paths.Base, "*", SearchOption.AllDirectories).Length == 1) { // We're the only file in the directory, so we can delete the entire directory - command += $" && rmdir \"{Directories.Base}\""; + command += $" && rmdir \"{Paths.Base}\""; } Process.Start(new ProcessStartInfo() @@ -179,17 +202,17 @@ public class Bootstrapper : Interfaces.IBootstrapper uninstallKey.SetValue("NoModify", 1); uninstallKey.SetValue("NoRepair", 1); - uninstallKey.SetValue("DisplayIcon", $"{Directories.Application},0"); + uninstallKey.SetValue("DisplayIcon", $"{Paths.Application},0"); uninstallKey.SetValue("DisplayName", Constants.PROJECT_NAME); uninstallKey.SetValue("DisplayVersion", Version); if (uninstallKey.GetValue("InstallDate") is null) uninstallKey.SetValue("InstallDate", DateTime.Now.ToString("yyyyMMdd")); - uninstallKey.SetValue("InstallLocation", Directories.Base); + uninstallKey.SetValue("InstallLocation", Paths.Base); uninstallKey.SetValue("Publisher", Constants.PROJECT_NAME); - uninstallKey.SetValue("QuietUninstallString", $"\"{Directories.Application}\" -uninstall -quiet"); - uninstallKey.SetValue("UninstallString", $"\"{Directories.Application}\" -uninstall"); + uninstallKey.SetValue("QuietUninstallString", $"\"{Paths.Application}\" -uninstall -quiet"); + uninstallKey.SetValue("UninstallString", $"\"{Paths.Application}\" -uninstall"); uninstallKey.SetValue("URLInfoAbout", $"https://github.com/{Constants.PROJECT_REPOSITORY}"); uninstallKey.SetValue("URLUpdateInfo", $"https://github.com/{Constants.PROJECT_REPOSITORY}/releases/latest"); } @@ -213,9 +236,9 @@ public class Bootstrapper : Interfaces.IBootstrapper public static bool License() { - if (!File.Exists(Directories.License)) + if (!File.Exists(Paths.License)) { - if (!AskForLicense(Directories.License)) + if (!AskForLicense(Paths.License)) { // User doesn't want to license this launcher return false; @@ -223,12 +246,12 @@ public class Bootstrapper : Interfaces.IBootstrapper } // Load the license... - while (!Web.LoadLicense(File.ReadAllText(Directories.License))) + while (!Web.LoadLicense(File.ReadAllText(Paths.License))) { // ...and if it's corrupt, keep asking for a new one. - File.Delete(Directories.License); + File.Delete(Paths.License); MessageBox.Show($"Corrupt license file! Please verify the contents of your license file (it should be named \"license.bin\".)", Constants.PROJECT_NAME, MessageBoxButtons.OK, MessageBoxIcon.Error); - AskForLicense(Directories.License, false); + AskForLicense(Paths.License, false); } return true; @@ -236,9 +259,9 @@ public class Bootstrapper : Interfaces.IBootstrapper public static void Unlicense() { - if (File.Exists(Directories.License)) + if (File.Exists(Paths.License)) { - File.Delete(Directories.License); + File.Delete(Paths.License); } } @@ -252,7 +275,7 @@ public class Bootstrapper : Interfaces.IBootstrapper { Title = "Select your license file", Filter = "License files (*.bin)|*.bin", - InitialDirectory = Win32.GetDownloadsPath() + InitialDirectory = KnownFolders.Downloads.Path }; if (dialog.ShowDialog() == DialogResult.OK) diff --git a/Kiseki.Launcher.Windows/Kiseki.Launcher.Windows.csproj b/Kiseki.Launcher.Windows/Kiseki.Launcher.Windows.csproj index f0d573b..b70cf0a 100644 --- a/Kiseki.Launcher.Windows/Kiseki.Launcher.Windows.csproj +++ b/Kiseki.Launcher.Windows/Kiseki.Launcher.Windows.csproj @@ -45,4 +45,9 @@ + + + + + \ No newline at end of file diff --git a/Kiseki.Launcher.Windows/Directories.cs b/Kiseki.Launcher.Windows/Paths.cs similarity index 79% rename from Kiseki.Launcher.Windows/Directories.cs rename to Kiseki.Launcher.Windows/Paths.cs index 3051ba4..6e716a6 100644 --- a/Kiseki.Launcher.Windows/Directories.cs +++ b/Kiseki.Launcher.Windows/Paths.cs @@ -1,8 +1,10 @@ namespace Kiseki.Launcher.Windows; -public static class Directories +public static class Paths { public static string LocalAppData => Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + public static string StartMenu => Environment.GetFolderPath(Environment.SpecialFolder.StartMenu); + public static string Desktop => Environment.GetFolderPath(Environment.SpecialFolder.Desktop); public static string Base { get; private set; } = ""; public static string Logs { get; private set; } = ""; diff --git a/Kiseki.Launcher.Windows/Program.cs b/Kiseki.Launcher.Windows/Program.cs index 8fa53ee..35e92c3 100644 --- a/Kiseki.Launcher.Windows/Program.cs +++ b/Kiseki.Launcher.Windows/Program.cs @@ -11,12 +11,12 @@ internal static class Program if (Path.GetFileName(Path.GetDirectoryName(Application.ExecutablePath))!.ToLower().Contains(Constants.PROJECT_NAME.ToLower())) { // Set to the current directory (user likely has installed the launcher, seeing as parent folder name contains the project name) - Directories.Initialize(Path.GetDirectoryName(Application.ExecutablePath)!); + Paths.Initialize(Path.GetDirectoryName(Application.ExecutablePath)!); } else { // Set to the default directory (user likely hasn't installed the launcher yet) - Directories.Initialize(Path.Combine(Directories.LocalAppData, Constants.PROJECT_NAME)); + Paths.Initialize(Path.Combine(Paths.LocalAppData, Constants.PROJECT_NAME)); } bool isConnected = Web.Initialize(); @@ -43,7 +43,7 @@ internal static class Program return; } - if (!File.Exists(Directories.Application)) + if (!File.Exists(Paths.Application)) { Bootstrapper.Install(); return; diff --git a/Kiseki.Launcher.Windows/Protocol.cs b/Kiseki.Launcher.Windows/Protocol.cs index 1bd067e..79fe126 100644 --- a/Kiseki.Launcher.Windows/Protocol.cs +++ b/Kiseki.Launcher.Windows/Protocol.cs @@ -6,7 +6,7 @@ public class Protocol : Interfaces.IProtocol { public static void Register() { - string arguments = $"\"{Directories.Application}\" \"%1\""; + string arguments = $"\"{Paths.Application}\" \"%1\""; RegistryKey uriKey = Registry.CurrentUser.CreateSubKey(@$"Software\Classes\{Constants.PROTOCOL_KEY}"); RegistryKey uriIconKey = uriKey.CreateSubKey("DefaultIcon"); diff --git a/Kiseki.Launcher.Windows/Win32.cs b/Kiseki.Launcher.Windows/Win32.cs index c3dc860..4235297 100644 --- a/Kiseki.Launcher.Windows/Win32.cs +++ b/Kiseki.Launcher.Windows/Win32.cs @@ -14,14 +14,5 @@ namespace Kiseki.Launcher.Windows ERROR_CANCELLED = 1223, ERROR_INTERNAL_ERROR = 1359 } - - // Source: https://www.codeproject.com/Articles/878605/Getting-All-Special-Folders-in-NET - public static string GetDownloadsPath() - { - return SHGetKnownFolderPath(new("374DE290-123F-4565-9164-39C4925E467B"), 0); - } - - [DllImport("shell32", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] - private static extern string SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, nint hToken = default); } } \ No newline at end of file