1
0
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:
Robert 2023-03-09 21:35:12 +01:00
parent 148eb99870
commit 0e32bb6b61
9 changed files with 139 additions and 73 deletions

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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
}

View File

@ -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);
}

View File

@ -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
{

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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