feat: add uninstall code
This commit is contained in:
parent
f68ce87cb5
commit
7890fa380a
|
|
@ -1,3 +1,4 @@
|
|||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
|
@ -15,14 +16,69 @@ namespace Kiseki.Launcher.Windows
|
|||
Directory.CreateDirectory(Directories.Base);
|
||||
}
|
||||
|
||||
// TODO: Implement this
|
||||
public static void Register()
|
||||
public static void Uninstall(bool quiet = false)
|
||||
{
|
||||
using (RegistryKey applicationKey = Registry.CurrentUser.CreateSubKey($@"Software\{Constants.PROJECT_NAME}"))
|
||||
DialogResult answer = quiet ? DialogResult.Yes : MessageBox.Show($"Are you sure you want to uninstall {Constants.PROJECT_NAME}?", Constants.PROJECT_NAME, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
||||
|
||||
if (answer != DialogResult.Yes)
|
||||
Environment.Exit((int)Win32.ErrorCode.ERROR_CANCELLED);
|
||||
|
||||
// Close active processes
|
||||
if (Process.GetProcessesByName($"{Constants.PROJECT_NAME}.Player").Any() || Process.GetProcessesByName($"{Constants.PROJECT_NAME}.Studio").Any())
|
||||
{
|
||||
applicationKey.SetValue("InstallLocation", Directories.Base);
|
||||
answer = quiet ? DialogResult.Yes : MessageBox.Show($"Kiseki is currently running. Would you like to close Kiseki now?", Constants.PROJECT_NAME, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
||||
|
||||
if (answer != DialogResult.Yes)
|
||||
Environment.Exit((int)Win32.ErrorCode.ERROR_CANCELLED);
|
||||
|
||||
try
|
||||
{
|
||||
foreach (Process process in Process.GetProcessesByName($"{Constants.PROJECT_NAME}.Player"))
|
||||
process.Kill();
|
||||
|
||||
foreach (Process process in Process.GetProcessesByName($"{Constants.PROJECT_NAME}.Studio"))
|
||||
process.Kill();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Environment.Exit((int)Win32.ErrorCode.ERROR_INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all files
|
||||
Directory.Delete(Directories.Logs, true);
|
||||
Directory.Delete(Directories.Versions, true);
|
||||
Directory.Delete(Directories.License);
|
||||
|
||||
// Cleanup our registry entries
|
||||
Unregister();
|
||||
Protocol.Unregister();
|
||||
|
||||
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}\"";
|
||||
|
||||
if (Directory.GetFiles(Directories.Base, "*", SearchOption.AllDirectories).Length == 1)
|
||||
{
|
||||
// We're the only file in the directory, so we can delete the entire directory
|
||||
command += $" && rmdir \"{Directories.Base}\"";
|
||||
}
|
||||
|
||||
Process.Start(new ProcessStartInfo()
|
||||
{
|
||||
FileName = "cmd.exe",
|
||||
Arguments = $"/c timeout 5 && {command}",
|
||||
UseShellExecute = true,
|
||||
WindowStyle = ProcessWindowStyle.Hidden
|
||||
});
|
||||
|
||||
Environment.Exit((int)Win32.ErrorCode.ERROR_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Register()
|
||||
{
|
||||
using RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{Constants.PROJECT_NAME}");
|
||||
|
||||
uninstallKey.SetValue("DisplayIcon", $"{Directories.Application},0");
|
||||
|
|
@ -42,10 +98,18 @@ namespace Kiseki.Launcher.Windows
|
|||
uninstallKey.SetValue("URLUpdateInfo", $"https://github.com/{Constants.PROJECT_REPOSITORY}/releases/latest");
|
||||
}
|
||||
|
||||
// TODO: Implement this
|
||||
public static void Unregister()
|
||||
{
|
||||
Registry.CurrentUser.DeleteSubKey($@"Software\{Constants.PROJECT_NAME}");
|
||||
try
|
||||
{
|
||||
Registry.CurrentUser.DeleteSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{Constants.PROJECT_NAME}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
#if DEBUG
|
||||
throw;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
|||
|
|
@ -47,6 +47,12 @@ namespace Kiseki.Launcher.Windows
|
|||
return;
|
||||
}
|
||||
|
||||
if (args[0] == "uninstall")
|
||||
{
|
||||
Launcher.Uninstall(args[0] == "-quiet");
|
||||
return;
|
||||
}
|
||||
|
||||
ApplicationConfiguration.Initialize();
|
||||
Application.Run(new MainWindow(args[0]));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,17 +6,17 @@ namespace Kiseki.Launcher.Windows
|
|||
{
|
||||
public const string PROTOCOL_KEY = "kiseki";
|
||||
|
||||
public void Register(string key, string name, string handler)
|
||||
public static void Register()
|
||||
{
|
||||
string arguments = $"\"{handler}\" \"%1\"";
|
||||
string arguments = $"\"{Directories.Application}\" \"%1\"";
|
||||
|
||||
RegistryKey uriKey = Registry.CurrentUser.CreateSubKey(@$"Software\Classes\{key}");
|
||||
RegistryKey uriKey = Registry.CurrentUser.CreateSubKey(@$"Software\Classes\{PROTOCOL_KEY}");
|
||||
RegistryKey uriIconKey = uriKey.CreateSubKey("DefaultIcon");
|
||||
RegistryKey uriCommandKey = uriKey.CreateSubKey(@"shell\open\command");
|
||||
|
||||
if (uriKey.GetValue("") is null)
|
||||
{
|
||||
uriKey.SetValue("", $"URL: {name} Protocol");
|
||||
uriKey.SetValue("", $"URL: {Constants.PROJECT_NAME} Protocol");
|
||||
uriKey.SetValue("URL Protocol", "");
|
||||
}
|
||||
|
||||
|
|
@ -30,9 +30,9 @@ namespace Kiseki.Launcher.Windows
|
|||
uriCommandKey.Close();
|
||||
}
|
||||
|
||||
public void Unregister(string key)
|
||||
public static void Unregister()
|
||||
{
|
||||
Registry.CurrentUser.DeleteSubKeyTree(@$"Software\Classes\{key}");
|
||||
Registry.CurrentUser.DeleteSubKeyTree(@$"Software\Classes\{PROTOCOL_KEY}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,13 +4,24 @@ namespace Kiseki.Launcher.Windows
|
|||
{
|
||||
public static class Win32
|
||||
{
|
||||
[DllImport("shell32", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
|
||||
private static extern string SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, nint hToken = default);
|
||||
// https://learn.microsoft.com/en-us/windows/win32/msi/error-codes
|
||||
// https://i-logic.com/serial/errorcodes.htm
|
||||
public enum ErrorCode
|
||||
{
|
||||
ERROR_SUCCESS = 0,
|
||||
ERROR_INSTALL_USEREXIT = 1602,
|
||||
ERROR_INSTALL_FAILURE = 1603,
|
||||
ERROR_CANCELLED = 1223,
|
||||
ERROR_INTERNAL_ERROR = 1359
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -49,6 +49,7 @@ namespace Kiseki.Launcher
|
|||
{
|
||||
PageHeadingChange("Downloading Kiseki...");
|
||||
ProgressBarStateChange(ProgressBarState.Normal);
|
||||
|
||||
marquee = false;
|
||||
}
|
||||
|
||||
|
|
@ -60,6 +61,7 @@ namespace Kiseki.Launcher
|
|||
await Task.Delay(2800);
|
||||
|
||||
yield return 4;
|
||||
|
||||
await Task.Delay(200);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ namespace Kiseki.Launcher.Helpers
|
|||
try
|
||||
{
|
||||
string json = Web.HttpClient.GetStringAsync(url).Result;
|
||||
|
||||
return JsonSerializer.Deserialize<T>(json);
|
||||
}
|
||||
catch
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ namespace Kiseki.Launcher
|
|||
public interface ILauncher
|
||||
{
|
||||
static abstract void Install();
|
||||
static abstract void Uninstall(bool quiet = false);
|
||||
static abstract void Register();
|
||||
static abstract void Unregister();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ namespace Kiseki.Launcher
|
|||
{
|
||||
public interface IProtocol
|
||||
{
|
||||
void Register(string key, string name, string handler);
|
||||
void Unregister(string key);
|
||||
static abstract void Register();
|
||||
static abstract void Unregister();
|
||||
}
|
||||
}
|
||||
|
|
@ -22,12 +22,11 @@ namespace Kiseki.Launcher
|
|||
CurrentUrl = IsInMaintenance ? $"{MAINTENANCE_DOMAIN}.{BASE_URL}" : BASE_URL;
|
||||
|
||||
int response = CheckHealth();
|
||||
|
||||
if (response != RESPONSE_SUCCESS)
|
||||
{
|
||||
if (response == RESPONSE_MAINTENANCE)
|
||||
{
|
||||
IsInMaintenance = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -55,10 +54,9 @@ namespace Kiseki.Launcher
|
|||
HttpClient.DefaultRequestHeaders.Clear();
|
||||
|
||||
var headers = JsonSerializer.Deserialize<Dictionary<string, string>>(license)!;
|
||||
|
||||
for (int i = 0; i < headers.Count; i++)
|
||||
{
|
||||
HttpClient.DefaultRequestHeaders.Add(headers.ElementAt(i).Key, headers.ElementAt(i).Value);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue