Improve install migrating

All Bloxstrap files are now copied instead of just the Bloxstrap executable
This commit is contained in:
pizzaboxer 2023-02-17 19:05:10 +00:00
parent e075e9b847
commit 1166ef9d60
6 changed files with 101 additions and 66 deletions

View File

@ -27,6 +27,7 @@ namespace Bloxstrap
public const string ProjectName = "Bloxstrap"; public const string ProjectName = "Bloxstrap";
public const string ProjectRepository = "pizzaboxer/bloxstrap"; public const string ProjectRepository = "pizzaboxer/bloxstrap";
// used only for communicating between app and menu - use Directories.Base for anything else
public static string BaseDirectory = null!; public static string BaseDirectory = null!;
public static bool ShouldSaveConfigs { get; set; } = false; public static bool ShouldSaveConfigs { get; set; } = false;
public static bool IsSetupComplete { get; set; } = true; public static bool IsSetupComplete { get; set; } = true;

View File

@ -67,6 +67,7 @@ namespace Bloxstrap
private readonly CancellationTokenSource _cancelTokenSource = new(); private readonly CancellationTokenSource _cancelTokenSource = new();
private static bool FreshInstall => String.IsNullOrEmpty(App.State.Prop.VersionGuid); private static bool FreshInstall => String.IsNullOrEmpty(App.State.Prop.VersionGuid);
private static string DesktopShortcutLocation => Path.Combine(Directories.Desktop, "Play Roblox.lnk");
private string? _launchCommandLine; private string? _launchCommandLine;
@ -114,6 +115,8 @@ namespace Bloxstrap
await CheckLatestVersion(); await CheckLatestVersion();
CheckInstallMigration();
// if bloxstrap is installing for the first time but is running, prompt to close roblox // if bloxstrap is installing for the first time but is running, prompt to close roblox
// if roblox needs updating but is running, ignore update for now // if roblox needs updating but is running, ignore update for now
if (!Directory.Exists(_versionFolder) && CheckIfRunning(true) || App.State.Prop.VersionGuid != _versionGuid && !CheckIfRunning(false)) if (!Directory.Exists(_versionFolder) && CheckIfRunning(true) || App.State.Prop.VersionGuid != _versionGuid && !CheckIfRunning(false))
@ -199,6 +202,69 @@ namespace Bloxstrap
_versionPackageManifest = await PackageManifest.Get(_versionGuid); _versionPackageManifest = await PackageManifest.Get(_versionGuid);
} }
private void CheckInstallMigration()
{
// check if we've changed our install location since the last time we started
// in which case, we'll have to copy over all our folders so we don't lose any mods and stuff
using RegistryKey? applicationKey = Registry.CurrentUser.OpenSubKey($@"Software\{App.ProjectName}", true);
string? oldInstallLocation = (string?)applicationKey?.GetValue("OldInstallLocation");
if (applicationKey is null || oldInstallLocation is null || oldInstallLocation == Directories.Base)
return;
SetStatus("Migrating install location...");
if (Directory.Exists(oldInstallLocation))
{
App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Moving all files in {oldInstallLocation} to {Directories.Base}...");
foreach (string oldFileLocation in Directory.GetFiles(oldInstallLocation, "*.*", SearchOption.AllDirectories))
{
string relativeFile = oldFileLocation.Substring(oldInstallLocation.Length + 1);
string newFileLocation = Path.Combine(Directories.Base, relativeFile);
string? newDirectory = Path.GetDirectoryName(newFileLocation);
try
{
if (!String.IsNullOrEmpty(newDirectory))
Directory.CreateDirectory(newDirectory);
File.Move(oldFileLocation, newFileLocation, true);
}
catch (Exception ex)
{
App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to move {oldFileLocation} to {newFileLocation}! {ex}");
}
}
try
{
Directory.Delete(oldInstallLocation, true);
App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Deleted old install location");
}
catch (Exception ex)
{
App.Logger.WriteLine($"[Bootstrapper::CheckInstallMigration] Failed to delete old install location! {ex}");
}
}
applicationKey.DeleteValue("OldInstallLocation");
// allow shortcuts to be re-registered
if (Directory.Exists(Directories.StartMenu))
Directory.Delete(Directories.StartMenu, true);
if (File.Exists(DesktopShortcutLocation))
{
File.Delete(DesktopShortcutLocation);
App.Settings.Prop.CreateDesktopIcon = true;
}
App.Logger.WriteLine("[Bootstrapper::CheckInstallMigration] Finished migrating install location!");
}
private bool CheckIfRunning(bool shutdown) private bool CheckIfRunning(bool shutdown)
{ {
App.Logger.WriteLine($"[Bootstrapper::CheckIfRunning] Checking if Roblox is running... (shutdown={shutdown})"); App.Logger.WriteLine($"[Bootstrapper::CheckIfRunning] Checking if Roblox is running... (shutdown={shutdown})");
@ -393,48 +459,32 @@ namespace Bloxstrap
#region App Install #region App Install
public static void Register() public static void Register()
{ {
RegistryKey applicationKey = Registry.CurrentUser.CreateSubKey($@"Software\{App.ProjectName}"); using (RegistryKey applicationKey = Registry.CurrentUser.CreateSubKey($@"Software\{App.ProjectName}"))
// new install location selected, delete old one
string? oldInstallLocation = (string?)applicationKey.GetValue("OldInstallLocation");
if (!String.IsNullOrEmpty(oldInstallLocation) && oldInstallLocation != Directories.Base)
{ {
try applicationKey.SetValue("InstallLocation", Directories.Base);
{
if (Directory.Exists(oldInstallLocation))
Directory.Delete(oldInstallLocation, true);
}
catch (Exception)
{
// ignored
}
applicationKey.DeleteValue("OldInstallLocation");
} }
applicationKey.SetValue("InstallLocation", Directories.Base);
applicationKey.Close();
// set uninstall key // set uninstall key
RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}"); using (RegistryKey uninstallKey = Registry.CurrentUser.CreateSubKey($@"Software\Microsoft\Windows\CurrentVersion\Uninstall\{App.ProjectName}"))
uninstallKey.SetValue("DisplayIcon", $"{Directories.Application},0"); {
uninstallKey.SetValue("DisplayName", App.ProjectName); uninstallKey.SetValue("DisplayIcon", $"{Directories.Application},0");
uninstallKey.SetValue("DisplayVersion", App.Version); uninstallKey.SetValue("DisplayName", App.ProjectName);
uninstallKey.SetValue("DisplayVersion", App.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", Directories.Base);
uninstallKey.SetValue("NoRepair", 1); uninstallKey.SetValue("NoRepair", 1);
uninstallKey.SetValue("Publisher", "pizzaboxer"); uninstallKey.SetValue("Publisher", "pizzaboxer");
uninstallKey.SetValue("ModifyPath", $"\"{Directories.Application}\" -menu"); uninstallKey.SetValue("ModifyPath", $"\"{Directories.Application}\" -menu");
uninstallKey.SetValue("QuietUninstallString", $"\"{Directories.Application}\" -uninstall -quiet"); uninstallKey.SetValue("QuietUninstallString", $"\"{Directories.Application}\" -uninstall -quiet");
uninstallKey.SetValue("UninstallString", $"\"{Directories.Application}\" -uninstall"); uninstallKey.SetValue("UninstallString", $"\"{Directories.Application}\" -uninstall");
uninstallKey.SetValue("URLInfoAbout", $"https://github.com/{App.ProjectRepository}"); uninstallKey.SetValue("URLInfoAbout", $"https://github.com/{App.ProjectRepository}");
uninstallKey.SetValue("URLUpdateInfo", $"https://github.com/{App.ProjectRepository}/releases/latest"); uninstallKey.SetValue("URLUpdateInfo", $"https://github.com/{App.ProjectRepository}/releases/latest");
uninstallKey.Close(); }
App.Logger.WriteLine("[Bootstrapper::StartRoblox] Registered application version"); App.Logger.WriteLine("[Bootstrapper::StartRoblox] Registered application");
} }
public static void CheckInstall() public static void CheckInstall()
@ -485,10 +535,10 @@ namespace Bloxstrap
if (App.Settings.Prop.CreateDesktopIcon) if (App.Settings.Prop.CreateDesktopIcon)
{ {
if (!File.Exists(Path.Combine(Directories.Desktop, "Play Roblox.lnk"))) if (!File.Exists(DesktopShortcutLocation))
{ {
ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0) ShellLink.Shortcut.CreateShortcut(Directories.Application, "", Directories.Application, 0)
.WriteToFile(Path.Combine(Directories.Desktop, "Play Roblox.lnk")); .WriteToFile(DesktopShortcutLocation);
} }
// one-time toggle, set it back to false // one-time toggle, set it back to false

View File

@ -41,7 +41,7 @@ namespace Bloxstrap.Helpers.Integrations
if (process.MainModule?.FileName is null) if (process.MainModule?.FileName is null)
continue; continue;
if (!process.MainModule.FileName.Contains(App.BaseDirectory)) if (!process.MainModule.FileName.Contains(Directories.Base))
continue; continue;
process.Kill(); process.Kill();
@ -56,7 +56,7 @@ namespace Bloxstrap.Helpers.Integrations
public static async Task CheckInstall() public static async Task CheckInstall()
{ {
string folderLocation = Path.Combine(App.BaseDirectory, "Integrations\\rbxfpsunlocker"); string folderLocation = Path.Combine(Directories.Base, "Integrations\\rbxfpsunlocker");
string fileLocation = Path.Combine(folderLocation, "rbxfpsunlocker.exe"); string fileLocation = Path.Combine(folderLocation, "rbxfpsunlocker.exe");
string settingsLocation = Path.Combine(folderLocation, "settings"); string settingsLocation = Path.Combine(folderLocation, "settings");

View File

@ -15,7 +15,7 @@ namespace Bloxstrap.Helpers
{ {
public class JsonManager<T> where T : new() public class JsonManager<T> where T : new()
{ {
public T Prop { get; set; } = new T(); public T Prop { get; set; } = new();
//public bool ShouldSave { get; set; } = true; //public bool ShouldSave { get; set; } = true;
public string FileLocation => Path.Combine(Directories.Base, $"{typeof(T).Name}.json"); public string FileLocation => Path.Combine(Directories.Base, $"{typeof(T).Name}.json");
//public string? FileLocation { get; set; } = null; //public string? FileLocation { get; set; } = null;

View File

@ -2,6 +2,7 @@
using System.IO; using System.IO;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using Bloxstrap.Helpers;
using Microsoft.Win32; using Microsoft.Win32;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Wpf.Ui.Controls.Interfaces; using Wpf.Ui.Controls.Interfaces;
@ -39,19 +40,11 @@ namespace Bloxstrap.ViewModels
try try
{ {
// check if we can write to the directory (a bit hacky but eh) // check if we can write to the directory (a bit hacky but eh)
string testFile = Path.Combine(App.BaseDirectory, $"{App.ProjectName}WriteTest.txt");
string testPath = App.BaseDirectory; Directory.CreateDirectory(App.BaseDirectory);
string testFile = Path.Combine(testPath, $"{App.ProjectName}WriteTest.txt");
bool testPathExists = Directory.Exists(testPath);
if (!testPathExists)
Directory.CreateDirectory(testPath);
File.WriteAllText(testFile, "hi"); File.WriteAllText(testFile, "hi");
File.Delete(testFile); File.Delete(testFile);
if (!testPathExists)
Directory.Delete(testPath);
} }
catch (UnauthorizedAccessException) catch (UnauthorizedAccessException)
{ {
@ -71,22 +64,13 @@ namespace Bloxstrap.ViewModels
if (App.BaseDirectory != _originalBaseDirectory) if (App.BaseDirectory != _originalBaseDirectory)
{ {
App.Logger.WriteLine($"[MainWindowViewModel::ConfirmSettings] Changing install location from {_originalBaseDirectory} to {App.BaseDirectory}");
App.ShowMessageBox($"{App.ProjectName} will install to the new location you've set the next time it runs.", MessageBoxImage.Information); App.ShowMessageBox($"{App.ProjectName} will install to the new location you've set the next time it runs.", MessageBoxImage.Information);
App.State.Prop.VersionGuid = ""; using RegistryKey registryKey = Registry.CurrentUser.CreateSubKey($@"Software\{App.ProjectName}");
registryKey.SetValue("InstallLocation", App.BaseDirectory);
using (RegistryKey registryKey = Registry.CurrentUser.CreateSubKey($@"Software\{App.ProjectName}")) registryKey.SetValue("OldInstallLocation", _originalBaseDirectory);
{ Directories.Initialize(App.BaseDirectory);
registryKey.SetValue("InstallLocation", App.BaseDirectory);
registryKey.SetValue("OldInstallLocation", _originalBaseDirectory);
registryKey.Close();
}
// preserve settings
// we don't need to copy the bootstrapper over since the install process will do that automatically
// App.Settings.Save();
// File.Copy(Path.Combine(App.BaseDirectory, "Settings.json"), Path.Combine(App.BaseDirectory, "Settings.json"));
} }
CloseWindow(); CloseWindow();

View File

@ -26,7 +26,7 @@
<ui:CardControl.Header> <ui:CardControl.Header>
<StackPanel> <StackPanel>
<TextBlock FontSize="14" Text="Automatically update Bloxstrap" /> <TextBlock FontSize="14" Text="Automatically update Bloxstrap" />
<TextBlock Margin="0,2,0,0" FontSize="12" Text="Bloxstrap will check and automatically update itself when launching Roblox." Foreground="{DynamicResource TextFillColorTertiaryBrush}" /> <TextBlock Margin="0,2,0,0" FontSize="12" Text="Bloxstrap will automatically check and update itself when launching Roblox." Foreground="{DynamicResource TextFillColorTertiaryBrush}" />
</StackPanel> </StackPanel>
</ui:CardControl.Header> </ui:CardControl.Header>
<ui:ToggleSwitch IsChecked="{Binding UpdateCheckingEnabled, Mode=TwoWay}" /> <ui:ToggleSwitch IsChecked="{Binding UpdateCheckingEnabled, Mode=TwoWay}" />
@ -44,7 +44,7 @@
<ui:CardControl.Header> <ui:CardControl.Header>
<StackPanel> <StackPanel>
<TextBlock FontSize="14" Text="Prompt on Roblox-forced channel change" /> <TextBlock FontSize="14" Text="Prompt on Roblox-forced channel change" />
<TextBlock Margin="0,2,0,0" FontSize="12" Text="Confirm change if Roblox mandates when launching. Otherwise, it'll change automatically." Foreground="{DynamicResource TextFillColorTertiaryBrush}" /> <TextBlock Margin="0,2,0,0" FontSize="12" Text="Bloxstrap will ask you if you want to change the release channel to what Roblox mandates." Foreground="{DynamicResource TextFillColorTertiaryBrush}" />
</StackPanel> </StackPanel>
</ui:CardControl.Header> </ui:CardControl.Header>
<ui:ToggleSwitch IsChecked="{Binding ChannelChangePromptingEnabled, Mode=TwoWay}" /> <ui:ToggleSwitch IsChecked="{Binding ChannelChangePromptingEnabled, Mode=TwoWay}" />