feat/chore: shortcuts, additional refactoring

This commit is contained in:
rjindael 2023-08-02 02:15:22 -07:00
parent 0350e39eca
commit 9b2d9707a9
No known key found for this signature in database
GPG Key ID: D069369C906CCF31
6 changed files with 61 additions and 40 deletions

View File

@ -5,6 +5,8 @@ using System.Reflection;
using Microsoft.Win32; using Microsoft.Win32;
using Syroot.Windows.IO;
public class Bootstrapper : Interfaces.IBootstrapper public class Bootstrapper : Interfaces.IBootstrapper
{ {
public readonly static string Version = Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2]; public readonly static string Version = Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2];
@ -88,16 +90,30 @@ public class Bootstrapper : Interfaces.IBootstrapper
Protocol.Unregister(); Protocol.Unregister();
Register(); Register();
Directory.CreateDirectory(Directories.Base); // Create paths
Directory.CreateDirectory(Directories.Versions); Directory.CreateDirectory(Paths.Base);
Directory.CreateDirectory(Directories.Logs); Directory.CreateDirectory(Paths.Versions);
Directory.CreateDirectory(Paths.Logs);
if (!File.Exists(Directories.Application)) // Copy ourselves
File.Copy(Application.ExecutablePath, Directories.Application, true); if (!File.Exists(Paths.Application))
File.Copy(Application.ExecutablePath, Paths.Application, true);
// Register us and our protocol handler system-wide
Register(); Register();
Protocol.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); MessageBox.Show($"Sucessfully installed {Constants.PROJECT_NAME}!", Constants.PROJECT_NAME, MessageBoxButtons.OK, MessageBoxIcon.Information);
Environment.Exit((int)Win32.ErrorCode.ERROR_SUCCESS); Environment.Exit((int)Win32.ErrorCode.ERROR_SUCCESS);
@ -133,14 +149,21 @@ public class Bootstrapper : Interfaces.IBootstrapper
} }
// Delete all files // Delete all files
if (Directory.Exists(Directories.Logs)) if (Directory.Exists(Paths.Logs))
Directory.Delete(Directories.Logs, true); Directory.Delete(Paths.Logs, true);
if (Directory.Exists(Directories.Versions)) if (Directory.Exists(Paths.Versions))
Directory.Delete(Directories.Versions, true); Directory.Delete(Paths.Versions, true);
if (File.Exists(Directories.License)) if (File.Exists(Paths.License))
File.Delete(Directories.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 // Cleanup our registry entries
Unregister(); 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); 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) 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 // 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() Process.Start(new ProcessStartInfo()
@ -179,17 +202,17 @@ public class Bootstrapper : Interfaces.IBootstrapper
uninstallKey.SetValue("NoModify", 1); uninstallKey.SetValue("NoModify", 1);
uninstallKey.SetValue("NoRepair", 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("DisplayName", Constants.PROJECT_NAME);
uninstallKey.SetValue("DisplayVersion", Version); uninstallKey.SetValue("DisplayVersion", Version);
if (uninstallKey.GetValue("InstallDate") is null) if (uninstallKey.GetValue("InstallDate") is null)
uninstallKey.SetValue("InstallDate", DateTime.Now.ToString("yyyyMMdd")); 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("Publisher", Constants.PROJECT_NAME);
uninstallKey.SetValue("QuietUninstallString", $"\"{Directories.Application}\" -uninstall -quiet"); uninstallKey.SetValue("QuietUninstallString", $"\"{Paths.Application}\" -uninstall -quiet");
uninstallKey.SetValue("UninstallString", $"\"{Directories.Application}\" -uninstall"); uninstallKey.SetValue("UninstallString", $"\"{Paths.Application}\" -uninstall");
uninstallKey.SetValue("URLInfoAbout", $"https://github.com/{Constants.PROJECT_REPOSITORY}"); uninstallKey.SetValue("URLInfoAbout", $"https://github.com/{Constants.PROJECT_REPOSITORY}");
uninstallKey.SetValue("URLUpdateInfo", $"https://github.com/{Constants.PROJECT_REPOSITORY}/releases/latest"); uninstallKey.SetValue("URLUpdateInfo", $"https://github.com/{Constants.PROJECT_REPOSITORY}/releases/latest");
} }
@ -213,9 +236,9 @@ public class Bootstrapper : Interfaces.IBootstrapper
public static bool License() 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 // User doesn't want to license this launcher
return false; return false;
@ -223,12 +246,12 @@ public class Bootstrapper : Interfaces.IBootstrapper
} }
// Load the license... // 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. // ...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); 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; return true;
@ -236,9 +259,9 @@ public class Bootstrapper : Interfaces.IBootstrapper
public static void Unlicense() 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", Title = "Select your license file",
Filter = "License files (*.bin)|*.bin", Filter = "License files (*.bin)|*.bin",
InitialDirectory = Win32.GetDownloadsPath() InitialDirectory = KnownFolders.Downloads.Path
}; };
if (dialog.ShowDialog() == DialogResult.OK) if (dialog.ShowDialog() == DialogResult.OK)

View File

@ -45,4 +45,9 @@
<ItemGroup> <ItemGroup>
<Compile Include="..\Kiseki.Launcher\**\*.cs" /> <Compile Include="..\Kiseki.Launcher\**\*.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="Syroot.Windows.IO.KnownFolders" Version="1.3.0" />
<PackageReference Include="securifybv.ShellLink" Version="0.1.0" />
</ItemGroup>
</Project> </Project>

View File

@ -1,8 +1,10 @@
namespace Kiseki.Launcher.Windows; namespace Kiseki.Launcher.Windows;
public static class Directories public static class Paths
{ {
public static string LocalAppData => Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); 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 Base { get; private set; } = "";
public static string Logs { get; private set; } = ""; public static string Logs { get; private set; } = "";

View File

@ -11,12 +11,12 @@ internal static class Program
if (Path.GetFileName(Path.GetDirectoryName(Application.ExecutablePath))!.ToLower().Contains(Constants.PROJECT_NAME.ToLower())) 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) // 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 else
{ {
// Set to the default directory (user likely hasn't installed the launcher yet) // 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(); bool isConnected = Web.Initialize();
@ -43,7 +43,7 @@ internal static class Program
return; return;
} }
if (!File.Exists(Directories.Application)) if (!File.Exists(Paths.Application))
{ {
Bootstrapper.Install(); Bootstrapper.Install();
return; return;

View File

@ -6,7 +6,7 @@ public class Protocol : Interfaces.IProtocol
{ {
public static void Register() 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 uriKey = Registry.CurrentUser.CreateSubKey(@$"Software\Classes\{Constants.PROTOCOL_KEY}");
RegistryKey uriIconKey = uriKey.CreateSubKey("DefaultIcon"); RegistryKey uriIconKey = uriKey.CreateSubKey("DefaultIcon");

View File

@ -14,14 +14,5 @@ namespace Kiseki.Launcher.Windows
ERROR_CANCELLED = 1223, ERROR_CANCELLED = 1223,
ERROR_INTERNAL_ERROR = 1359 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);
} }
} }