mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-12 21:38:38 +00:00
Output install log to file
This commit is contained in:
parent
148eb99870
commit
0e32bb6b61
@ -15,13 +15,14 @@ public class ReleaseRepository : IReleaseRepository
|
||||
_repository.Database.GetCollection<ReleaseEntity>().EnsureIndex(s => s.Version, true);
|
||||
}
|
||||
|
||||
public void SaveVersionInstallDate(string version)
|
||||
public bool SaveVersionInstallDate(string version)
|
||||
{
|
||||
ReleaseEntity release = _repository.Query<ReleaseEntity>().Where(r => r.Version == version).FirstOrDefault();
|
||||
if (release != null)
|
||||
return;
|
||||
return false;
|
||||
|
||||
_repository.Insert(new ReleaseEntity {Version = version, InstalledAt = DateTimeOffset.UtcNow});
|
||||
return true;
|
||||
}
|
||||
|
||||
public ReleaseEntity GetPreviousInstalledVersion()
|
||||
@ -32,6 +33,6 @@ public class ReleaseRepository : IReleaseRepository
|
||||
|
||||
public interface IReleaseRepository : IRepository
|
||||
{
|
||||
void SaveVersionInstallDate(string version);
|
||||
bool SaveVersionInstallDate(string version);
|
||||
ReleaseEntity GetPreviousInstalledVersion();
|
||||
}
|
||||
@ -99,18 +99,12 @@ public class ApplicationStateManager
|
||||
argsList.Add("--autorun");
|
||||
|
||||
// Retain startup arguments after update by providing them to the script
|
||||
string script = $"\"{Path.Combine(Constants.UpdatingFolder, "installing", "scripts", "update.ps1")}\"";
|
||||
string script = Path.Combine(Constants.UpdatingFolder, "installing", "scripts", "update.ps1");
|
||||
string source = $"-sourceDirectory \"{Path.Combine(Constants.UpdatingFolder, "installing")}\"";
|
||||
string destination = $"-destinationDirectory \"{Constants.ApplicationFolder}\"";
|
||||
string args = argsList.Any() ? $"-artemisArgs \"{string.Join(',', argsList)}\"" : "";
|
||||
|
||||
// Run the PowerShell script included in the new version, that way any changes made to the script are used
|
||||
ProcessStartInfo info = new()
|
||||
{
|
||||
Arguments = $"-File {script} {source} {destination} {args}",
|
||||
FileName = "PowerShell.exe"
|
||||
};
|
||||
Process.Start(info);
|
||||
RunScriptWithOutputFile(script, $"{source} {destination} {args}", Path.Combine(Constants.DataFolder, "update-log.txt"));
|
||||
|
||||
// Lets try a graceful shutdown, PowerShell will kill if needed
|
||||
if (Application.Current?.ApplicationLifetime is IControlledApplicationLifetime controlledApplicationLifetime)
|
||||
@ -142,6 +136,20 @@ public class ApplicationStateManager
|
||||
Process.Start(info);
|
||||
}
|
||||
|
||||
private void RunScriptWithOutputFile(string script, string arguments, string outputFile)
|
||||
{
|
||||
// Use > for files that are bigger than 200kb to start fresh, otherwise use >> to append
|
||||
string redirectSymbol = File.Exists(outputFile) && new FileInfo(outputFile).Length > 200000 ? ">" : ">>";
|
||||
ProcessStartInfo info = new()
|
||||
{
|
||||
Arguments = $"PowerShell -File \"{script}\" {arguments} {redirectSymbol} \"{outputFile}\"",
|
||||
FileName = "PowerShell.exe",
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
CreateNoWindow = true,
|
||||
};
|
||||
Process.Start(info);
|
||||
}
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("user32.dll")]
|
||||
private static extern int GetSystemMetrics(int nIndex);
|
||||
}
|
||||
@ -35,30 +35,12 @@ public class WindowsUpdateNotificationProvider : IUpdateNotificationProvider
|
||||
ToastNotificationManagerCompat.OnActivated += ToastNotificationManagerCompatOnOnActivated;
|
||||
}
|
||||
|
||||
private async void ToastNotificationManagerCompatOnOnActivated(ToastNotificationActivatedEventArgsCompat e)
|
||||
{
|
||||
ToastArguments args = ToastArguments.Parse(e.Argument);
|
||||
Guid releaseId = Guid.Parse(args.Get("releaseId"));
|
||||
string releaseVersion = args.Get("releaseVersion");
|
||||
string action = "view-changes";
|
||||
if (args.Contains("action"))
|
||||
action = args.Get("action");
|
||||
|
||||
if (action == "install")
|
||||
await InstallRelease(releaseId, releaseVersion);
|
||||
else if (action == "view-changes")
|
||||
ViewRelease(releaseId);
|
||||
else if (action == "cancel")
|
||||
_cancellationTokenSource?.Cancel();
|
||||
else if (action == "restart-for-update")
|
||||
_updateService.RestartForUpdate(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ShowNotification(Guid releaseId, string releaseVersion)
|
||||
{
|
||||
GetBuilderForRelease(releaseId, releaseVersion)
|
||||
.AddText("Update available")
|
||||
.AddText($"Artemis version {releaseVersion} has been released")
|
||||
.AddText($"Artemis {releaseVersion} has been released")
|
||||
.AddButton(new ToastButton()
|
||||
.SetContent("Install")
|
||||
.AddArgument("action", "install").SetAfterActivationBehavior(ToastAfterActivationBehavior.PendingUpdate))
|
||||
@ -66,14 +48,24 @@ public class WindowsUpdateNotificationProvider : IUpdateNotificationProvider
|
||||
.Show(t => t.Tag = releaseId.ToString());
|
||||
}
|
||||
|
||||
private void ViewRelease(Guid releaseId)
|
||||
/// <inheritdoc />
|
||||
public void ShowInstalledNotification(string installedVersion)
|
||||
{
|
||||
new ToastContentBuilder().AddArgument("releaseVersion", installedVersion)
|
||||
.AddText("Update installed")
|
||||
.AddText($"Artemis {installedVersion} has been installed")
|
||||
.AddButton(new ToastButton().SetContent("View changes").AddArgument("action", "view-changes"))
|
||||
.Show();
|
||||
}
|
||||
|
||||
private void ViewRelease(string releaseVersion)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
_mainWindowService.OpenMainWindow();
|
||||
if (_mainWindowService.HostScreen == null)
|
||||
return;
|
||||
|
||||
|
||||
// TODO: When proper routing has been implemented, use that here
|
||||
// Create a settings VM to navigate to
|
||||
SettingsViewModel settingsViewModel = _getSettingsViewModel(_mainWindowService.HostScreen);
|
||||
@ -83,7 +75,7 @@ public class WindowsUpdateNotificationProvider : IUpdateNotificationProvider
|
||||
// Navigate to the settings VM
|
||||
_mainWindowService.HostScreen.Router.Navigate.Execute(settingsViewModel);
|
||||
// Navigate to the release tab
|
||||
releaseTabViewModel.PreselectId = releaseId;
|
||||
releaseTabViewModel.PreselectVersion = releaseVersion;
|
||||
settingsViewModel.SelectedTab = releaseTabViewModel;
|
||||
});
|
||||
}
|
||||
@ -128,10 +120,18 @@ public class WindowsUpdateNotificationProvider : IUpdateNotificationProvider
|
||||
installer.PropertyChanged -= InstallerOnPropertyChanged;
|
||||
}
|
||||
|
||||
// If the main window is not open the user isn't busy, restart straight away
|
||||
if (!_mainWindowService.IsMainWindowOpen)
|
||||
{
|
||||
_updateService.RestartForUpdate(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ask for a restart because the user is actively using Artemis
|
||||
GetBuilderForRelease(releaseId, releaseVersion)
|
||||
.AddAudio(new ToastAudio {Silent = true})
|
||||
.AddText("Update ready")
|
||||
.AddText($"Artemis version {releaseVersion} is ready to be applied")
|
||||
.AddText("Artemis must restart to finish the update")
|
||||
.AddButton(new ToastButton().SetContent("Restart Artemis").AddArgument("action", "restart-for-update"))
|
||||
.AddButton(new ToastButton().SetContent("Later").AddArgument("action", "postpone-update"))
|
||||
.Show(t => t.Tag = releaseId.ToString());
|
||||
@ -160,4 +160,24 @@ public class WindowsUpdateNotificationProvider : IUpdateNotificationProvider
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private async void ToastNotificationManagerCompatOnOnActivated(ToastNotificationActivatedEventArgsCompat e)
|
||||
{
|
||||
ToastArguments args = ToastArguments.Parse(e.Argument);
|
||||
|
||||
Guid releaseId = args.Contains("releaseId") ? Guid.Parse(args.Get("releaseId")) : Guid.Empty;
|
||||
string releaseVersion = args.Get("releaseVersion");
|
||||
string action = "view-changes";
|
||||
if (args.Contains("action"))
|
||||
action = args.Get("action");
|
||||
|
||||
if (action == "install")
|
||||
await InstallRelease(releaseId, releaseVersion);
|
||||
else if (action == "view-changes")
|
||||
ViewRelease(releaseVersion);
|
||||
else if (action == "cancel")
|
||||
_cancellationTokenSource?.Cancel();
|
||||
else if (action == "restart-for-update")
|
||||
_updateService.RestartForUpdate(false);
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,16 @@
|
||||
param (
|
||||
[Parameter(Mandatory=$true)][string]$sourceDirectory,
|
||||
[Parameter(Mandatory=$true)][string]$destinationDirectory,
|
||||
[Parameter(Mandatory=$false)][string]$artemisArgs
|
||||
[Parameter(Mandatory = $true)][string]$sourceDirectory,
|
||||
[Parameter(Mandatory = $true)][string]$destinationDirectory,
|
||||
[Parameter(Mandatory = $false)][string]$artemisArgs
|
||||
)
|
||||
|
||||
Write-Host "Artemis update script v1"
|
||||
Write-Host "Please do not close this window, this should not take long"
|
||||
Write-Host ""
|
||||
|
||||
# Wait up to 10 seconds for the process to shut down
|
||||
for ($i=1; $i -le 10; $i++) {
|
||||
for ($i = 1; $i -le 10; $i++) {
|
||||
$process = Get-Process -Name Artemis.UI.Windows -ErrorAction SilentlyContinue
|
||||
if (!$process) {
|
||||
if (!$process)
|
||||
{
|
||||
break
|
||||
}
|
||||
Write-Host "Waiting for Artemis to shut down ($i / 10)"
|
||||
@ -20,13 +19,15 @@ for ($i=1; $i -le 10; $i++) {
|
||||
|
||||
# If the process is still running, kill it
|
||||
$process = Get-Process -Name Artemis.UI.Windows -ErrorAction SilentlyContinue
|
||||
if ($process) {
|
||||
if ($process)
|
||||
{
|
||||
Stop-Process -Id $process.Id -Force
|
||||
Start-Sleep -Seconds 1
|
||||
}
|
||||
|
||||
# Check if the destination directory exists
|
||||
if (!(Test-Path $destinationDirectory)) {
|
||||
if (!(Test-Path $destinationDirectory))
|
||||
{
|
||||
Write-Error "The destination directory does not exist"
|
||||
}
|
||||
|
||||
@ -44,8 +45,11 @@ Write-Host "Finished! Restarting Artemis"
|
||||
Start-Sleep -Seconds 1
|
||||
|
||||
# When finished, run the updated version
|
||||
if ($artemisArgs) {
|
||||
if ($artemisArgs)
|
||||
{
|
||||
Start-Process -FilePath "$destinationDirectory\Artemis.UI.Windows.exe" -WorkingDirectory $destinationDirectory -ArgumentList $artemisArgs
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Start-Process -FilePath "$destinationDirectory\Artemis.UI.Windows.exe" -WorkingDirectory $destinationDirectory
|
||||
}
|
||||
@ -36,7 +36,7 @@ public static class ContainerExtensions
|
||||
|
||||
container.Register<NodeScriptWindowViewModelBase, NodeScriptWindowViewModel>(Reuse.Singleton);
|
||||
container.Register<IPropertyVmFactory, PropertyVmFactory>(Reuse.Singleton);
|
||||
container.Register<IUpdateNotificationProvider, InAppUpdateNotificationProvider>();
|
||||
container.Register<IUpdateNotificationProvider, BasicUpdateNotificationProvider>();
|
||||
|
||||
container.RegisterMany(thisAssembly, type => type.IsAssignableTo<IArtemisUIService>(), Reuse.Singleton);
|
||||
}
|
||||
|
||||
@ -54,14 +54,14 @@ public class ReleasesTabViewModel : ActivatableViewModelBase
|
||||
{
|
||||
await _updateService.CacheLatestRelease();
|
||||
await GetMoreReleases(d.AsCancellationToken());
|
||||
SelectedReleaseViewModel = ReleaseViewModels.FirstOrDefault(r => r.ReleaseId == PreselectId) ?? ReleaseViewModels.FirstOrDefault();
|
||||
SelectedReleaseViewModel = ReleaseViewModels.FirstOrDefault(r => r.Version == PreselectVersion) ?? ReleaseViewModels.FirstOrDefault();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public ReadOnlyObservableCollection<ReleaseViewModel> ReleaseViewModels { get; }
|
||||
public string Channel { get; }
|
||||
public Guid? PreselectId { get; set; }
|
||||
public string? PreselectVersion { get; set; }
|
||||
|
||||
public ReleaseViewModel? SelectedReleaseViewModel
|
||||
{
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.UI.Screens.Settings;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.Builders;
|
||||
@ -9,35 +8,67 @@ using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Services.Updating;
|
||||
|
||||
public class InAppUpdateNotificationProvider : IUpdateNotificationProvider
|
||||
public class BasicUpdateNotificationProvider : IUpdateNotificationProvider
|
||||
{
|
||||
private readonly Func<IScreen, SettingsViewModel> _getSettingsViewModel;
|
||||
private readonly IMainWindowService _mainWindowService;
|
||||
private readonly INotificationService _notificationService;
|
||||
private Action? _notification;
|
||||
private Action? _available;
|
||||
private Action? _installed;
|
||||
|
||||
public InAppUpdateNotificationProvider(INotificationService notificationService, IMainWindowService mainWindowService, Func<IScreen, SettingsViewModel> getSettingsViewModel)
|
||||
public BasicUpdateNotificationProvider(INotificationService notificationService, IMainWindowService mainWindowService, Func<IScreen, SettingsViewModel> getSettingsViewModel)
|
||||
{
|
||||
_notificationService = notificationService;
|
||||
_mainWindowService = mainWindowService;
|
||||
_getSettingsViewModel = getSettingsViewModel;
|
||||
}
|
||||
|
||||
private void ShowInAppNotification(Guid releaseId, string releaseVersion)
|
||||
/// <inheritdoc />
|
||||
public void ShowNotification(Guid releaseId, string releaseVersion)
|
||||
{
|
||||
_notification?.Invoke();
|
||||
_notification = _notificationService.CreateNotification()
|
||||
if (_mainWindowService.IsMainWindowOpen)
|
||||
ShowAvailable(releaseVersion);
|
||||
else
|
||||
_mainWindowService.MainWindowOpened += (_, _) => ShowAvailable(releaseVersion);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ShowInstalledNotification(string installedVersion)
|
||||
{
|
||||
if (_mainWindowService.IsMainWindowOpen)
|
||||
ShowInstalled(installedVersion);
|
||||
else
|
||||
_mainWindowService.MainWindowOpened += (_, _) => ShowInstalled(installedVersion);
|
||||
}
|
||||
|
||||
private void ShowAvailable(string releaseVersion)
|
||||
{
|
||||
_available?.Invoke();
|
||||
_available = _notificationService.CreateNotification()
|
||||
.WithTitle("Update available")
|
||||
.WithMessage($"Artemis version {releaseVersion} has been released")
|
||||
.WithMessage($"Artemis {releaseVersion} has been released")
|
||||
.WithSeverity(NotificationSeverity.Success)
|
||||
.WithTimeout(TimeSpan.FromSeconds(15))
|
||||
.HavingButton(b => b.WithText("View release").WithAction(() => ViewRelease(releaseId)))
|
||||
.HavingButton(b => b.WithText("View release").WithAction(() => ViewRelease(releaseVersion)))
|
||||
.Show();
|
||||
}
|
||||
|
||||
private void ViewRelease(Guid releaseId)
|
||||
private void ShowInstalled(string installedVersion)
|
||||
{
|
||||
_notification?.Invoke();
|
||||
_installed?.Invoke();
|
||||
_installed = _notificationService.CreateNotification()
|
||||
.WithTitle("Update installed")
|
||||
.WithMessage($"Artemis {installedVersion} has been installed.")
|
||||
.WithSeverity(NotificationSeverity.Success)
|
||||
.WithTimeout(TimeSpan.FromSeconds(15))
|
||||
.HavingButton(b => b.WithText("View release").WithAction(() => ViewRelease(installedVersion)))
|
||||
.Show();
|
||||
}
|
||||
|
||||
private void ViewRelease(string version)
|
||||
{
|
||||
_installed?.Invoke();
|
||||
_available?.Invoke();
|
||||
|
||||
if (_mainWindowService.HostScreen == null)
|
||||
return;
|
||||
@ -51,16 +82,7 @@ public class InAppUpdateNotificationProvider : IUpdateNotificationProvider
|
||||
// Navigate to the settings VM
|
||||
_mainWindowService.HostScreen.Router.Navigate.Execute(settingsViewModel);
|
||||
// Navigate to the release tab
|
||||
releaseTabViewModel.PreselectId = releaseId;
|
||||
releaseTabViewModel.PreselectVersion = version;
|
||||
settingsViewModel.SelectedTab = releaseTabViewModel;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ShowNotification(Guid releaseId, string releaseVersion)
|
||||
{
|
||||
if (_mainWindowService.IsMainWindowOpen)
|
||||
ShowInAppNotification(releaseId, releaseVersion);
|
||||
else
|
||||
_mainWindowService.MainWindowOpened += (_, _) => ShowInAppNotification(releaseId, releaseVersion);
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Artemis.UI.Services.Updating;
|
||||
|
||||
public interface IUpdateNotificationProvider
|
||||
{
|
||||
void ShowNotification(Guid releaseId, string releaseVersion);
|
||||
void ShowInstalledNotification(string installedVersion);
|
||||
}
|
||||
@ -66,7 +66,7 @@ public class UpdateService : IUpdateService
|
||||
private void ProcessReleaseStatus()
|
||||
{
|
||||
string currentVersion = Constants.CurrentVersion;
|
||||
_releaseRepository.SaveVersionInstallDate(currentVersion);
|
||||
bool updated = _releaseRepository.SaveVersionInstallDate(currentVersion);
|
||||
PreviousVersion = _releaseRepository.GetPreviousInstalledVersion()?.Version;
|
||||
|
||||
if (!Directory.Exists(Constants.UpdatingFolder))
|
||||
@ -88,6 +88,9 @@ public class UpdateService : IUpdateService
|
||||
_logger.Warning(e, "Failed to clean up old update file at {FilePath}", file);
|
||||
}
|
||||
}
|
||||
|
||||
// if (updated)
|
||||
_updateNotificationProvider.Value.ShowInstalledNotification(currentVersion);
|
||||
}
|
||||
|
||||
private void ShowUpdateNotification(IGetNextRelease_NextPublishedRelease release)
|
||||
@ -194,7 +197,15 @@ public class UpdateService : IUpdateService
|
||||
if (Directory.Exists(Path.Combine(Constants.UpdatingFolder, "installing")))
|
||||
{
|
||||
_logger.Warning("Cleaning up leftover installing folder, did an update go wrong?");
|
||||
Directory.Delete(Path.Combine(Constants.UpdatingFolder, "installing"));
|
||||
try
|
||||
{
|
||||
Directory.Delete(Path.Combine(Constants.UpdatingFolder, "installing"), true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error(e, "Failed to delete leftover installing folder");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If an update is pending, don't bother with anything else
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user