mirror of
https://github.com/bloxstraplabs/bloxstrap.git
synced 2025-04-21 10:01:27 -07:00
Abandon staging folder idea, use lockfile instead
thank you matt for helping me see sense through this one
This commit is contained in:
parent
72df157eb8
commit
99ff002121
@ -39,13 +39,13 @@ namespace Bloxstrap.AppData
|
|||||||
{ "extracontent-places.zip", @"ExtraContent\places\" },
|
{ "extracontent-places.zip", @"ExtraContent\places\" },
|
||||||
};
|
};
|
||||||
|
|
||||||
public virtual string FinalDirectory { get; } = null!;
|
|
||||||
|
|
||||||
public string StagingDirectory => $"{FinalDirectory}.staging";
|
|
||||||
|
|
||||||
public virtual string ExecutableName { get; } = null!;
|
public virtual string ExecutableName { get; } = null!;
|
||||||
|
|
||||||
public string ExecutablePath => Path.Combine(FinalDirectory, ExecutableName);
|
public virtual string Directory { get; } = null!;
|
||||||
|
|
||||||
|
public string LockFilePath => Path.Combine(Directory, "Bloxstrap.lock");
|
||||||
|
|
||||||
|
public string ExecutablePath => Path.Combine(Directory, ExecutableName);
|
||||||
|
|
||||||
public virtual IReadOnlyDictionary<string, string> PackageDirectoryMap { get; set; }
|
public virtual IReadOnlyDictionary<string, string> PackageDirectoryMap { get; set; }
|
||||||
|
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
|
|
||||||
string StartEvent { get; }
|
string StartEvent { get; }
|
||||||
|
|
||||||
string FinalDirectory { get; }
|
string Directory { get; }
|
||||||
|
|
||||||
string StagingDirectory { get; }
|
string LockFilePath { get; }
|
||||||
|
|
||||||
string ExecutablePath { get; }
|
string ExecutablePath { get; }
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ namespace Bloxstrap.AppData
|
|||||||
|
|
||||||
public string StartEvent => "www.roblox.com/robloxStartedEvent";
|
public string StartEvent => "www.roblox.com/robloxStartedEvent";
|
||||||
|
|
||||||
public override string FinalDirectory => Path.Combine(Paths.Roblox, "Player");
|
public override string Directory => Path.Combine(Paths.Roblox, "Player");
|
||||||
|
|
||||||
public AppState State => App.State.Prop.Player;
|
public AppState State => App.State.Prop.Player;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
public string StartEvent => "www.roblox.com/robloxStudioStartedEvent";
|
public string StartEvent => "www.roblox.com/robloxStudioStartedEvent";
|
||||||
|
|
||||||
public override string FinalDirectory => Path.Combine(Paths.Roblox, "Studio");
|
public override string Directory => Path.Combine(Paths.Roblox, "Studio");
|
||||||
|
|
||||||
public AppState State => App.State.Prop.Studio;
|
public AppState State => App.State.Prop.Studio;
|
||||||
|
|
||||||
|
@ -47,6 +47,9 @@ namespace Bloxstrap
|
|||||||
private double _progressIncrement;
|
private double _progressIncrement;
|
||||||
private long _totalDownloadedBytes = 0;
|
private long _totalDownloadedBytes = 0;
|
||||||
|
|
||||||
|
private bool _mustUpgrade => File.Exists(AppData.LockFilePath) || !File.Exists(AppData.ExecutablePath);
|
||||||
|
private bool _skipUpgrade = false;
|
||||||
|
|
||||||
public IBootstrapperDialog? Dialog = null;
|
public IBootstrapperDialog? Dialog = null;
|
||||||
|
|
||||||
public bool IsStudioLaunch => _launchMode != LaunchMode.Player;
|
public bool IsStudioLaunch => _launchMode != LaunchMode.Player;
|
||||||
@ -162,8 +165,8 @@ namespace Bloxstrap
|
|||||||
await GetLatestVersionInfo();
|
await GetLatestVersionInfo();
|
||||||
|
|
||||||
// install/update roblox if we're running for the first time, needs updating, or the player location doesn't exist
|
// install/update roblox if we're running for the first time, needs updating, or the player location doesn't exist
|
||||||
if (!File.Exists(AppData.ExecutablePath) || AppData.State.VersionGuid != _latestVersionGuid)
|
if (!_skipUpgrade && (AppData.State.VersionGuid != _latestVersionGuid || _mustUpgrade))
|
||||||
await InstallLatestVersion();
|
await UpgradeRoblox();
|
||||||
|
|
||||||
//await ApplyModifications();
|
//await ApplyModifications();
|
||||||
|
|
||||||
@ -284,7 +287,7 @@ namespace Bloxstrap
|
|||||||
{
|
{
|
||||||
FileName = AppData.ExecutablePath,
|
FileName = AppData.ExecutablePath,
|
||||||
Arguments = _launchCommandLine,
|
Arguments = _launchCommandLine,
|
||||||
WorkingDirectory = AppData.FinalDirectory
|
WorkingDirectory = AppData.Directory
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_launchMode == LaunchMode.StudioAuth)
|
if (_launchMode == LaunchMode.StudioAuth)
|
||||||
@ -362,14 +365,17 @@ namespace Bloxstrap
|
|||||||
{
|
{
|
||||||
using var ipl = new InterProcessLock("Watcher", TimeSpan.FromSeconds(5));
|
using var ipl = new InterProcessLock("Watcher", TimeSpan.FromSeconds(5));
|
||||||
|
|
||||||
|
// TODO: look into if this needs to be launched *before* roblox starts
|
||||||
if (ipl.IsAcquired)
|
if (ipl.IsAcquired)
|
||||||
Process.Start(Paths.Process, $"-watcher \"{args}\"");
|
Process.Start(Paths.Process, $"-watcher \"{args}\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CancelInstall()
|
// TODO: the bootstrapper dialogs call this function directly.
|
||||||
|
// this should probably be behind an event invocation.
|
||||||
|
public void Cancel()
|
||||||
{
|
{
|
||||||
const string LOG_IDENT = "Bootstrapper::CancelInstall";
|
const string LOG_IDENT = "Bootstrapper::Cancel";
|
||||||
|
|
||||||
if (!_isInstalling)
|
if (!_isInstalling)
|
||||||
{
|
{
|
||||||
@ -381,21 +387,24 @@ namespace Bloxstrap
|
|||||||
if (_cancelTokenSource.IsCancellationRequested)
|
if (_cancelTokenSource.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
App.Logger.WriteLine(LOG_IDENT, "Cancelling install...");
|
App.Logger.WriteLine(LOG_IDENT, "Cancelling launch...");
|
||||||
|
|
||||||
_cancelTokenSource.Cancel();
|
_cancelTokenSource.Cancel();
|
||||||
|
|
||||||
|
if (_isInstalling)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// clean up install
|
// clean up install
|
||||||
if (Directory.Exists(AppData.StagingDirectory))
|
if (Directory.Exists(AppData.Directory))
|
||||||
Directory.Delete(AppData.StagingDirectory, true);
|
Directory.Delete(AppData.Directory, true);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
App.Logger.WriteLine(LOG_IDENT, "Could not fully clean up installation!");
|
App.Logger.WriteLine(LOG_IDENT, "Could not fully clean up installation!");
|
||||||
App.Logger.WriteException(LOG_IDENT, ex);
|
App.Logger.WriteException(LOG_IDENT, ex);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Dialog?.CloseBootstrapper();
|
Dialog?.CloseBootstrapper();
|
||||||
|
|
||||||
@ -509,11 +518,9 @@ namespace Bloxstrap
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Roblox Install
|
#region Roblox Install
|
||||||
private async Task InstallLatestVersion()
|
private async Task UpgradeRoblox()
|
||||||
{
|
{
|
||||||
const string LOG_IDENT = "Bootstrapper::InstallLatestVersion";
|
const string LOG_IDENT = "Bootstrapper::UpgradeRoblox";
|
||||||
|
|
||||||
_isInstalling = true;
|
|
||||||
|
|
||||||
SetStatus(FreshInstall ? Strings.Bootstrapper_Status_Installing : Strings.Bootstrapper_Status_Upgrading);
|
SetStatus(FreshInstall ? Strings.Bootstrapper_Status_Installing : Strings.Bootstrapper_Status_Upgrading);
|
||||||
|
|
||||||
@ -521,10 +528,36 @@ namespace Bloxstrap
|
|||||||
Directory.CreateDirectory(Paths.Downloads);
|
Directory.CreateDirectory(Paths.Downloads);
|
||||||
Directory.CreateDirectory(Paths.Roblox);
|
Directory.CreateDirectory(Paths.Roblox);
|
||||||
|
|
||||||
if (Directory.Exists(AppData.StagingDirectory))
|
if (Directory.Exists(AppData.Directory))
|
||||||
Directory.Delete(AppData.StagingDirectory, true);
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// gross hack to see if roblox is still running
|
||||||
|
// i don't want to rely on mutexes because they can change, and will false flag for
|
||||||
|
// running installations that are not by bloxstrap
|
||||||
|
File.Delete(AppData.ExecutablePath);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
App.Logger.WriteLine(LOG_IDENT, "Could not delete executable/folder, Roblox may still be running. Aborting update.");
|
||||||
|
App.Logger.WriteException(LOG_IDENT, ex);
|
||||||
|
|
||||||
Directory.CreateDirectory(AppData.StagingDirectory);
|
Directory.Delete(AppData.Directory);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.Delete(AppData.Directory, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_isInstalling = true;
|
||||||
|
|
||||||
|
Directory.CreateDirectory(AppData.Directory);
|
||||||
|
|
||||||
|
// installer lock, it should only be present while roblox is in the process of upgrading
|
||||||
|
// if it's present while we're launching, then it's an unfinished install and must be reinstalled
|
||||||
|
var lockFile = new FileInfo(AppData.LockFilePath);
|
||||||
|
lockFile.Create().Dispose();
|
||||||
|
|
||||||
// package manifest states packed size and uncompressed size in exact bytes
|
// package manifest states packed size and uncompressed size in exact bytes
|
||||||
// packed size only matters if we don't already have the package cached on disk
|
// packed size only matters if we don't already have the package cached on disk
|
||||||
@ -564,8 +597,7 @@ namespace Bloxstrap
|
|||||||
if (package.Name == "WebView2RuntimeInstaller.zip")
|
if (package.Name == "WebView2RuntimeInstaller.zip")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// extract the package immediately after download asynchronously
|
// extract the package async immediately after download
|
||||||
// discard is just used to suppress the warning
|
|
||||||
extractionTasks.Add(Task.Run(() => ExtractPackage(package), _cancelTokenSource.Token));
|
extractionTasks.Add(Task.Run(() => ExtractPackage(package), _cancelTokenSource.Token));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,11 +618,13 @@ namespace Bloxstrap
|
|||||||
await Task.WhenAll(extractionTasks);
|
await Task.WhenAll(extractionTasks);
|
||||||
|
|
||||||
App.Logger.WriteLine(LOG_IDENT, "Writing AppSettings.xml...");
|
App.Logger.WriteLine(LOG_IDENT, "Writing AppSettings.xml...");
|
||||||
await File.WriteAllTextAsync(Path.Combine(AppData.StagingDirectory, "AppSettings.xml"), AppSettings);
|
await File.WriteAllTextAsync(Path.Combine(AppData.Directory, "AppSettings.xml"), AppSettings);
|
||||||
|
|
||||||
if (_cancelTokenSource.IsCancellationRequested)
|
if (_cancelTokenSource.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// only prompt on fresh install, since we don't want to be prompting them for every single launch
|
||||||
|
// TODO: state entry?
|
||||||
if (FreshInstall)
|
if (FreshInstall)
|
||||||
{
|
{
|
||||||
using var hklmKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WOW6432Node\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}");
|
using var hklmKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WOW6432Node\\Microsoft\\EdgeUpdate\\Clients\\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}");
|
||||||
@ -612,7 +646,7 @@ namespace Bloxstrap
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string baseDirectory = Path.Combine(AppData.StagingDirectory, AppData.PackageDirectoryMap[package.Name]);
|
string baseDirectory = Path.Combine(AppData.Directory, AppData.PackageDirectoryMap[package.Name]);
|
||||||
|
|
||||||
ExtractPackage(package);
|
ExtractPackage(package);
|
||||||
|
|
||||||
@ -681,37 +715,13 @@ namespace Bloxstrap
|
|||||||
|
|
||||||
App.Logger.WriteLine(LOG_IDENT, $"Registered as {totalSize} KB");
|
App.Logger.WriteLine(LOG_IDENT, $"Registered as {totalSize} KB");
|
||||||
|
|
||||||
|
App.State.Save();
|
||||||
|
|
||||||
|
lockFile.Delete();
|
||||||
|
|
||||||
if (Dialog is not null)
|
if (Dialog is not null)
|
||||||
Dialog.CancelEnabled = false;
|
Dialog.CancelEnabled = false;
|
||||||
|
|
||||||
if (Directory.Exists(AppData.FinalDirectory))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// gross hack to see if roblox is still running
|
|
||||||
// i don't want to rely on mutexes because they can change, and will false flag for
|
|
||||||
// running installations that are not by bloxstrap
|
|
||||||
File.Delete(AppData.ExecutablePath);
|
|
||||||
|
|
||||||
Directory.Delete(AppData.FinalDirectory, true);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
App.Logger.WriteLine(LOG_IDENT, "Could not delete executable/folder, Roblox may still be running. Aborting update.");
|
|
||||||
App.Logger.WriteException(LOG_IDENT, ex);
|
|
||||||
|
|
||||||
Directory.Delete(AppData.StagingDirectory);
|
|
||||||
|
|
||||||
_isInstalling = false;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Directory.Move(AppData.StagingDirectory, AppData.FinalDirectory);
|
|
||||||
|
|
||||||
App.State.Save();
|
|
||||||
|
|
||||||
_isInstalling = false;
|
_isInstalling = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -996,7 +1006,7 @@ namespace Bloxstrap
|
|||||||
const string LOG_IDENT = "Bootstrapper::ExtractPackage";
|
const string LOG_IDENT = "Bootstrapper::ExtractPackage";
|
||||||
|
|
||||||
string packageLocation = Path.Combine(Paths.Downloads, package.Signature);
|
string packageLocation = Path.Combine(Paths.Downloads, package.Signature);
|
||||||
string packageFolder = Path.Combine(AppData.StagingDirectory, AppData.PackageDirectoryMap[package.Name]);
|
string packageFolder = Path.Combine(AppData.Directory, AppData.PackageDirectoryMap[package.Name]);
|
||||||
|
|
||||||
App.Logger.WriteLine(LOG_IDENT, $"Extracting {package.Name}...");
|
App.Logger.WriteLine(LOG_IDENT, $"Extracting {package.Name}...");
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ namespace Bloxstrap.UI.Elements.Bootstrapper.Base
|
|||||||
public void Dialog_FormClosing(object sender, FormClosingEventArgs e)
|
public void Dialog_FormClosing(object sender, FormClosingEventArgs e)
|
||||||
{
|
{
|
||||||
if (!_isClosing)
|
if (!_isClosing)
|
||||||
Bootstrapper?.CancelInstall();
|
Bootstrapper?.Cancel();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
|
|||||||
private void Window_Closing(object sender, CancelEventArgs e)
|
private void Window_Closing(object sender, CancelEventArgs e)
|
||||||
{
|
{
|
||||||
if (!_isClosing)
|
if (!_isClosing)
|
||||||
Bootstrapper?.CancelInstall();
|
Bootstrapper?.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IBootstrapperDialog Methods
|
#region IBootstrapperDialog Methods
|
||||||
|
@ -88,7 +88,7 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
|
|||||||
private void UiWindow_Closing(object sender, CancelEventArgs e)
|
private void UiWindow_Closing(object sender, CancelEventArgs e)
|
||||||
{
|
{
|
||||||
if (!_isClosing)
|
if (!_isClosing)
|
||||||
Bootstrapper?.CancelInstall();
|
Bootstrapper?.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IBootstrapperDialog Methods
|
#region IBootstrapperDialog Methods
|
||||||
|
@ -102,7 +102,7 @@ namespace Bloxstrap.UI.Elements.Bootstrapper
|
|||||||
private void UiWindow_Closing(object sender, CancelEventArgs e)
|
private void UiWindow_Closing(object sender, CancelEventArgs e)
|
||||||
{
|
{
|
||||||
if (!_isClosing)
|
if (!_isClosing)
|
||||||
Bootstrapper?.CancelInstall();
|
Bootstrapper?.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IBootstrapperDialog Methods
|
#region IBootstrapperDialog Methods
|
||||||
|
@ -35,7 +35,7 @@ namespace Bloxstrap.UI.ViewModels.Bootstrapper
|
|||||||
|
|
||||||
private void CancelInstall()
|
private void CancelInstall()
|
||||||
{
|
{
|
||||||
_dialog.Bootstrapper?.CancelInstall();
|
_dialog.Bootstrapper?.Cancel();
|
||||||
_dialog.CloseBootstrapper();
|
_dialog.CloseBootstrapper();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user