Install location warning, +reliable uninstalling

This commit is contained in:
pizzaboxer 2023-07-02 23:46:16 +01:00
parent 34b6fef148
commit 7cda363fa7
No known key found for this signature in database
GPG Key ID: 59D4A1DBAD0F2BA8
5 changed files with 99 additions and 47 deletions

View File

@ -683,43 +683,68 @@ namespace Bloxstrap
ProtocolHandler.Register("roblox-player", "Roblox", bootstrapperLocation);
}
try
// if the folder we're installed to does not end with "Bloxstrap", we're installed to a user-selected folder
// in which case, chances are they chose to install to somewhere they didn't really mean to (prior to the added warning in 2.4.0)
// if so, we're walking on eggshells and have to ensure we only clean up what we need to clean up
bool cautiousUninstall = !Directories.Base.EndsWith(App.ProjectName);
var cleanupSequence = new List<Action>
{
// delete application key
Registry.CurrentUser.DeleteSubKey($@"Software\{App.ProjectName}");
() => Registry.CurrentUser.DeleteSubKey($@"Software\{App.ProjectName}"),
() => Directory.Delete(Directories.StartMenu, true),
() => File.Delete(Path.Combine(Directories.Desktop, "Play Roblox.lnk")),
() => Registry.CurrentUser.DeleteSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}")
};
// delete start menu folder
Directory.Delete(Directories.StartMenu, true);
// delete desktop shortcut
File.Delete(Path.Combine(Directories.Desktop, "Play Roblox.lnk"));
// delete uninstall key
Registry.CurrentUser.DeleteSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}");
// delete installation folder
// (should delete everything except bloxstrap itself)
Directory.Delete(Directories.Base, true);
if (cautiousUninstall)
{
cleanupSequence.Add(() => Directory.Delete(Directories.Downloads, true));
cleanupSequence.Add(() => Directory.Delete(Directories.Modifications, true));
cleanupSequence.Add(() => Directory.Delete(Directories.Versions, true));
cleanupSequence.Add(() => Directory.Delete(Directories.Logs, true));
cleanupSequence.Add(() => File.Delete(App.Settings.FileLocation));
cleanupSequence.Add(() => File.Delete(App.State.FileLocation));
}
catch (Exception ex)
else
{
App.Logger.WriteLine($"Could not fully uninstall! ({ex})");
cleanupSequence.Add(() => Directory.Delete(Directories.Base, true));
}
foreach (var process in cleanupSequence)
{
try
{
process();
}
catch (Exception ex)
{
App.Logger.WriteLine($"[Bootstrapper::Uninstall] Encountered exception when running cleanup sequence (#{cleanupSequence.IndexOf(process)})");
App.Logger.WriteLine($"[Bootstrapper::Uninstall] {ex}");
}
}
Action? callback = null;
if (Directory.Exists(Directories.Base))
{
callback = () =>
callback = delegate
{
// this is definitely one of the workaround hacks of all time
// could antiviruses falsely detect this as malicious behaviour though?
// "hmm whats this program doing running a cmd command chain quietly in the background that auto deletes an entire folder"
string deleteCommand;
if (cautiousUninstall)
deleteCommand = $"del /Q \"{Directories.Application}\"";
else
deleteCommand = $"del /Q \"{Directories.Base}\\*\" && rmdir \"{Directories.Base}\"";
Process.Start(new ProcessStartInfo()
{
FileName = "cmd.exe",
Arguments = $"/c timeout 5 && del /Q \"{Directories.Base}\\*\" && rmdir \"{Directories.Base}\"",
Arguments = $"/c timeout 5 && {deleteCommand}",
UseShellExecute = true,
WindowStyle = ProcessWindowStyle.Hidden
});

View File

@ -15,23 +15,27 @@ namespace Bloxstrap
public static string Base { get; private set; } = "";
public static string Downloads { get; private set; } = "";
public static string Logs { get; private set; } = "";
public static string Integrations { get; private set; } = "";
public static string Versions { get; private set; } = "";
public static string Modifications { get; private set; } = "";
public static string Application { get; private set; } = "";
public static bool Initialized => string.IsNullOrEmpty(Base);
public static bool Initialized => !String.IsNullOrEmpty(Base);
public static void Initialize(string baseDirectory)
{
Base = baseDirectory;
Downloads = Path.Combine(Base, "Downloads");
Logs = Path.Combine(Base, "Logs");
Integrations = Path.Combine(Base, "Integrations");
Versions = Path.Combine(Base, "Versions");
Modifications = Path.Combine(Base, "Modifications");
Application = Path.Combine(Base, $"{App.ProjectName}.exe");
}
}
}

View File

@ -56,9 +56,9 @@ namespace Bloxstrap
FileLocation = location;
// clean up any logs older than a week
if (!useTempDir)
if (Directories.Initialized && Directory.Exists(Directories.Logs))
{
foreach (FileInfo log in new DirectoryInfo(directory).GetFiles())
foreach (FileInfo log in new DirectoryInfo(Directories.Logs).GetFiles())
{
if (log.LastWriteTimeUtc.AddDays(7) > DateTime.UtcNow)
continue;

View File

@ -69,10 +69,7 @@ namespace Bloxstrap.UI.ViewModels.Menu
if (dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK)
return;
if (!dialog.SelectedPath.EndsWith(App.ProjectName))
InstallLocation = Path.Combine(dialog.SelectedPath, App.ProjectName);
else
InstallLocation = dialog.SelectedPath;
InstallLocation = dialog.SelectedPath;
OnPropertyChanged(nameof(InstallLocation));
}

View File

@ -10,7 +10,7 @@ using CommunityToolkit.Mvvm.Input;
using Wpf.Ui.Controls.Interfaces;
using Wpf.Ui.Mvvm.Contracts;
using Bloxstrap.UI.MessageBox;
using System.Linq;
namespace Bloxstrap.UI.ViewModels.Menu
{
@ -41,27 +41,53 @@ namespace Bloxstrap.UI.ViewModels.Menu
return;
}
try
{
// check if we can write to the directory (a bit hacky but eh)
string testFile = Path.Combine(App.BaseDirectory, $"{App.ProjectName}WriteTest.txt");
bool shouldCheckInstallLocation = App.IsFirstRun || App.BaseDirectory != _originalBaseDirectory;
Directory.CreateDirectory(App.BaseDirectory);
File.WriteAllText(testFile, "hi");
File.Delete(testFile);
}
catch (UnauthorizedAccessException)
if (shouldCheckInstallLocation)
{
Controls.ShowMessageBox(
$"{App.ProjectName} does not have write access to the install location you selected. Please choose another install location.",
MessageBoxImage.Error
);
return;
}
catch (Exception ex)
{
Controls.ShowMessageBox(ex.Message, MessageBoxImage.Error);
return;
try
{
// check if we can write to the directory (a bit hacky but eh)
string testFile = Path.Combine(App.BaseDirectory, $"{App.ProjectName}WriteTest.txt");
Directory.CreateDirectory(App.BaseDirectory);
File.WriteAllText(testFile, "hi");
File.Delete(testFile);
}
catch (UnauthorizedAccessException)
{
Controls.ShowMessageBox(
$"{App.ProjectName} does not have write access to the install location you've selected. Please choose another location.",
MessageBoxImage.Error
);
return;
}
catch (Exception ex)
{
Controls.ShowMessageBox(ex.Message, MessageBoxImage.Error);
return;
}
if (!App.BaseDirectory.EndsWith(App.ProjectName) && Directory.Exists(App.BaseDirectory) && Directory.EnumerateFileSystemEntries(App.BaseDirectory).Any())
{
string suggestedChange = Path.Combine(App.BaseDirectory, App.ProjectName);
MessageBoxResult result = Controls.ShowMessageBox(
$"The folder you've chosen to install {App.ProjectName} to already exists and is NOT empty. It is strongly recommended for {App.ProjectName} to be installed to its own independent folder.\n\n" +
"Changing to the following location is suggested:\n" +
$"{suggestedChange}\n\n" +
"Would you like to change your install location to this?\n" +
"Selecting 'No' will ignore this warning and continue installation.",
MessageBoxImage.Warning,
MessageBoxButton.YesNoCancel,
MessageBoxResult.Yes
);
if (result == MessageBoxResult.Yes)
App.BaseDirectory = suggestedChange;
else if (result == MessageBoxResult.Cancel)
return;
}
}
if (!App.IsFirstRun)
@ -69,7 +95,7 @@ namespace Bloxstrap.UI.ViewModels.Menu
App.ShouldSaveConfigs = true;
App.FastFlags.Save();
if (App.BaseDirectory != _originalBaseDirectory)
if (shouldCheckInstallLocation)
{
App.Logger.WriteLine($"[MainWindowViewModel::ConfirmSettings] Changing install location from {_originalBaseDirectory} to {App.BaseDirectory}");