Skip to content

Commit

Permalink
Install location warning, +reliable uninstalling
Browse files Browse the repository at this point in the history
  • Loading branch information
pizzaboxer committed Jul 2, 2023
1 parent 34b6fef commit 7cda363
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 47 deletions.
63 changes: 44 additions & 19 deletions Bloxstrap/Bootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -683,43 +683,68 @@ private void Uninstall()
ProtocolHandler.Register("roblox-player", "Roblox", bootstrapperLocation);
}

try
{
// delete application key
Registry.CurrentUser.DeleteSubKey($@"Software\{App.ProjectName}");

// delete start menu folder
Directory.Delete(Directories.StartMenu, true);

// delete desktop shortcut
File.Delete(Path.Combine(Directories.Desktop, "Play Roblox.lnk"));
// 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);

// delete uninstall key
Registry.CurrentUser.DeleteSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}");
var cleanupSequence = new List<Action>
{
() => 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 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));
}
else
{
cleanupSequence.Add(() => Directory.Delete(Directories.Base, true));
}
catch (Exception ex)

foreach (var process in cleanupSequence)
{
App.Logger.WriteLine($"Could not fully uninstall! ({ex})");
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
});
Expand Down
6 changes: 5 additions & 1 deletion Bloxstrap/Directories.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,27 @@ static class Directories

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");


}
}
}
4 changes: 2 additions & 2 deletions Bloxstrap/Logger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ public void Initialize(bool useTempDir = false)
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;
Expand Down
5 changes: 1 addition & 4 deletions Bloxstrap/UI/ViewModels/Menu/InstallationViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,7 @@ private void BrowseInstallLocation()
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));
}
Expand Down
68 changes: 47 additions & 21 deletions Bloxstrap/UI/ViewModels/Menu/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
using Wpf.Ui.Controls.Interfaces;
using Wpf.Ui.Mvvm.Contracts;

using Bloxstrap.UI.MessageBox;
using System.Linq;

namespace Bloxstrap.UI.ViewModels.Menu
{
Expand Down Expand Up @@ -41,35 +41,61 @@ private void ConfirmSettings()
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)
{
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)
if (shouldCheckInstallLocation)
{
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)
{
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}");

Expand Down

0 comments on commit 7cda363

Please sign in to comment.