From b03a6f50efe74b25e7a2c12e7026979c75afd71b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 17 Jun 2025 12:59:09 +0200 Subject: [PATCH 01/12] Lay ground to be able to run multiple operations before and after an operation --- .../AbstractOperation.cs | 272 +++++++----------- .../AbstractOperation_Auxiliaries.cs | 100 +++++++ .../PackageOperations.cs | 31 +- .../ProcessOperation.cs | 5 +- src/UniGetUI/AppOperationHelper.cs | 50 ++++ .../SoftwarePages/InstalledPackagesPage.cs | 7 +- .../SoftwarePages/SoftwareUpdatesPage.cs | 7 +- 7 files changed, 295 insertions(+), 177 deletions(-) create mode 100644 src/UniGetUI.PackageEngine.Operations/AbstractOperation_Auxiliaries.cs diff --git a/src/UniGetUI.PackageEngine.Operations/AbstractOperation.cs b/src/UniGetUI.PackageEngine.Operations/AbstractOperation.cs index f19bc881ce..ae11c47d72 100644 --- a/src/UniGetUI.PackageEngine.Operations/AbstractOperation.cs +++ b/src/UniGetUI.PackageEngine.Operations/AbstractOperation.cs @@ -2,67 +2,13 @@ using UniGetUI.Core.SettingsEngine; using UniGetUI.Core.Tools; using UniGetUI.PackageEngine.Enums; +using YamlDotNet.Serialization.ObjectGraphVisitors; namespace UniGetUI.PackageOperations; -public abstract class AbstractOperation : IDisposable +public abstract partial class AbstractOperation : IDisposable { - public static class RetryMode - { - public const string NoRetry = ""; - public const string Retry = "Retry"; - public const string Retry_AsAdmin = "RetryAsAdmin"; - public const string Retry_Interactive = "RetryInteractive"; - public const string Retry_SkipIntegrity = "RetryNoHashCheck"; - } - - public class OperationMetadata - { - /// - /// Installation of X - /// - public string Title = ""; - - /// - /// X is being installed/upated/removed - /// - public string Status = ""; - - /// - /// X was installed - /// - public string SuccessTitle = ""; - - /// - /// X has been installed successfully - /// - public string SuccessMessage = ""; - - /// - /// X could not be installed. - /// - public string FailureTitle = ""; - - /// - /// X Could not be installed - /// - public string FailureMessage = ""; - - /// - /// Starting operation X with options Y - /// - public string OperationInformation = ""; - - public readonly string Identifier; - - public OperationMetadata() - { - Identifier = new Random().NextInt64(1000000, 9999999).ToString(); - } - } - public readonly OperationMetadata Metadata = new(); - public static readonly List OperationQueue = []; public event EventHandler? StatusChanged; public event EventHandler? CancelRequested; @@ -72,38 +18,12 @@ public OperationMetadata() public event EventHandler? Enqueued; public event EventHandler? OperationSucceeded; public event EventHandler? OperationFailed; - - public static int MAX_OPERATIONS; - public event EventHandler? BadgesChanged; - public class BadgeCollection - { - public readonly bool AsAdministrator; - public readonly bool Interactive; - public readonly bool SkipHashCheck; - public readonly string? Scope; - - public BadgeCollection(bool admin, bool interactive, bool skiphash, string? scope) - { - AsAdministrator = admin; - Interactive = interactive; - SkipHashCheck = skiphash; - Scope = scope; - } - } - public void ApplyCapabilities(bool admin, bool interactive, bool skiphash, string? scope) - { - BadgesChanged?.Invoke(this, new BadgeCollection(admin, interactive, skiphash, scope)); - } - - public enum LineType - { - VerboseDetails, - ProgressIndicator, - Information, - Error - } + public bool Started { get; private set; } + protected bool QUEUE_ENABLED; + protected bool FORCE_HOLD_QUEUE; + private bool IsInnerOperation = false; private readonly List<(string, LineType)> LogList = []; private OperationStatus _status = OperationStatus.InQueue; @@ -113,20 +33,23 @@ public OperationStatus Status set { _status = value; StatusChanged?.Invoke(this, value); } } - public bool Started { get; private set; } - protected bool QUEUE_ENABLED; - protected bool FORCE_HOLD_QUEUE; + public void ApplyCapabilities(bool admin, bool interactive, bool skiphash, string? scope) + { + BadgesChanged?.Invoke(this, new BadgeCollection(admin, interactive, skiphash, scope)); + } - private readonly AbstractOperation? requirement; + // private readonly AbstractOperation? requirement; + private readonly IReadOnlyList PreOperations = []; + private readonly IReadOnlyList PostOperations = []; - public AbstractOperation(bool queue_enabled, AbstractOperation? req) + public AbstractOperation( + bool queue_enabled, + IReadOnlyList? preOps = null, + IReadOnlyList? postOps = null) { QUEUE_ENABLED = queue_enabled; - if (req is not null) - { - requirement = req; - QUEUE_ENABLED = false; - } + if (preOps is not null) PreOperations = preOps; + if (postOps is not null) PostOperations = postOps; Status = OperationStatus.InQueue; Line("Please wait...", LineType.ProgressIndicator); @@ -202,20 +125,9 @@ public async Task MainThread() Enqueued?.Invoke(this, EventArgs.Empty); - if (requirement != null) - { // OPERATION REQUIREMENT HANDLER - Logger.Info($"Operation {Metadata.Title} is waiting for requirement operation {requirement.Metadata.Title}"); - Line(CoreTools.Translate("Waiting for {0} to complete...", requirement.Metadata.Title), LineType.ProgressIndicator); - { - while (requirement.Status is OperationStatus.Running or OperationStatus.InQueue) - { - await Task.Delay(100); - if (SKIP_QUEUE) break; - } - } - } - else if (QUEUE_ENABLED) - { // QUEUE HANDLER + if (QUEUE_ENABLED && !IsInnerOperation) + { + // QUEUE HANDLER SKIP_QUEUE = false; OperationQueue.Add(this); int lastPos = -2; @@ -238,61 +150,8 @@ public async Task MainThread() } // END QUEUE HANDLER - // BEGIN ACTUAL OPERATION - OperationVeredict result; - Line(CoreTools.Translate("Starting operation..."), LineType.ProgressIndicator); - if (Status is OperationStatus.InQueue) Status = OperationStatus.Running; - - do - { - OperationStarting?.Invoke(this, EventArgs.Empty); - - try - { - // Check if the operation was canceled - if (Status is OperationStatus.Canceled) - { - result = OperationVeredict.Canceled; - break; - } - - if (requirement is not null) - { - if (requirement.Status is OperationStatus.Failed) - { - Line(CoreTools.Translate("{0} has failed, that was a requirement for {1} to be run", requirement.Metadata.Title, Metadata.Title), LineType.Error); - result = OperationVeredict.Failure; - break; - } - - if (requirement.Status is OperationStatus.Canceled) - { - Line(CoreTools.Translate("The user has canceled {0}, that was a requirement for {1} to be run", requirement.Metadata.Title, Metadata.Title), LineType.Error); - result = OperationVeredict.Canceled; - break; - } - } - - Task op = PerformOperation(); - while (Status != OperationStatus.Canceled && !op.IsCompleted) await Task.Delay(100); - - if (Status is OperationStatus.Canceled) result = OperationVeredict.Canceled; - else result = op.GetAwaiter().GetResult(); - } - catch (Exception e) - { - result = OperationVeredict.Failure; - Logger.Error(e); - foreach (string l in e.ToString().Split("\n")) - { - Line(l, LineType.Error); - } - } - } while (result == OperationVeredict.AutoRetry); - - + var result = await _runOperation(); while (OperationQueue.Remove(this)); - // END OPERATION if (result == OperationVeredict.Success) { @@ -352,6 +211,91 @@ public async Task MainThread() } } + private async Task _runOperation() + { + OperationVeredict result; + + // Process preoperations + int i = 0, count = PreOperations.Count; + if(count > 0) Line("", LineType.VerboseDetails); + foreach (var preReq in PreOperations) + { + i++; + Line(CoreTools.Translate($"Running PreOperation ({i}/{count})..."), LineType.Information); + preReq.Operation.LogLineAdded += (_, line) => Line(line.Item1, line.Item2); + await preReq.Operation.MainThread(); + if (preReq.Operation.Status is not OperationStatus.Succeeded && preReq.MustSucceed) + { + Line( + CoreTools.Translate($"PreOperation {i} out of {count} failed, and was tagged as necessary. Aborting..."), + LineType.Error); + return OperationVeredict.Failure; + } + Line(CoreTools.Translate($"PreOperation {i} out of {count} finished with result {preReq.Operation.Status}"), LineType.Information); + Line("--------------------------------", LineType.Information); + Line("", LineType.VerboseDetails); + } + + // BEGIN ACTUAL OPERATION + Line(CoreTools.Translate("Starting operation..."), LineType.Information); + if (Status is OperationStatus.InQueue) Status = OperationStatus.Running; + + do + { + OperationStarting?.Invoke(this, EventArgs.Empty); + + try + { + // Check if the operation was canceled + if (Status is OperationStatus.Canceled) + { + result = OperationVeredict.Canceled; + break; + } + + Task op = PerformOperation(); + while (Status != OperationStatus.Canceled && !op.IsCompleted) await Task.Delay(100); + + if (Status is OperationStatus.Canceled) result = OperationVeredict.Canceled; + else result = op.GetAwaiter().GetResult(); + } + catch (Exception e) + { + result = OperationVeredict.Failure; + Logger.Error(e); + foreach (string l in e.ToString().Split("\n")) + { + Line(l, LineType.Error); + } + } + } while (result is OperationVeredict.AutoRetry); + + if (result is not OperationVeredict.Success) + return result; + + // Process postoperations + i = 0; count = PostOperations.Count; + foreach (var postReq in PostOperations) + { + i++; + Line("--------------------------------", LineType.Information); + Line("", LineType.VerboseDetails); + Line(CoreTools.Translate($"Running PostOperation ({i}/{count})..."), LineType.Information); + postReq.Operation.LogLineAdded += (_, line) => Line(line.Item1, line.Item2); + await postReq.Operation.MainThread(); + if (postReq.Operation.Status is not OperationStatus.Succeeded && postReq.MustSucceed) + { + Line( + CoreTools.Translate($"PostOperation {i} out of {count} failed, and was tagged as necessary. Aborting..."), + LineType.Error); + return OperationVeredict.Failure; + } + Line(CoreTools.Translate($"PostOperation {i} out of {count} finished with result {postReq.Operation.Status}"), LineType.Information); + } + + return result; + } + private bool SKIP_QUEUE; public void SkipQueue() diff --git a/src/UniGetUI.PackageEngine.Operations/AbstractOperation_Auxiliaries.cs b/src/UniGetUI.PackageEngine.Operations/AbstractOperation_Auxiliaries.cs new file mode 100644 index 0000000000..b41d60a12b --- /dev/null +++ b/src/UniGetUI.PackageEngine.Operations/AbstractOperation_Auxiliaries.cs @@ -0,0 +1,100 @@ +namespace UniGetUI.PackageOperations; + +public abstract partial class AbstractOperation +{ + public static readonly List OperationQueue = []; + public static int MAX_OPERATIONS; + + public static class RetryMode + { + public const string NoRetry = ""; + public const string Retry = "Retry"; + public const string Retry_AsAdmin = "RetryAsAdmin"; + public const string Retry_Interactive = "RetryInteractive"; + public const string Retry_SkipIntegrity = "RetryNoHashCheck"; + } + + public class OperationMetadata + { + /// + /// Installation of X + /// + public string Title = ""; + + /// + /// X is being installed/upated/removed + /// + public string Status = ""; + + /// + /// X was installed + /// + public string SuccessTitle = ""; + + /// + /// X has been installed successfully + /// + public string SuccessMessage = ""; + + /// + /// X could not be installed. + /// + public string FailureTitle = ""; + + /// + /// X Could not be installed + /// + public string FailureMessage = ""; + + /// + /// Starting operation X with options Y + /// + public string OperationInformation = ""; + + public readonly string Identifier; + + public OperationMetadata() + { + Identifier = new Random().NextInt64(1000000, 9999999).ToString(); + } + } + + public class BadgeCollection + { + public readonly bool AsAdministrator; + public readonly bool Interactive; + public readonly bool SkipHashCheck; + public readonly string? Scope; + + public BadgeCollection(bool admin, bool interactive, bool skiphash, string? scope) + { + AsAdministrator = admin; + Interactive = interactive; + SkipHashCheck = skiphash; + Scope = scope; + } + } + + public enum LineType + { + VerboseDetails, + ProgressIndicator, + Information, + Error + } + + + public struct InnerOperation + { + public readonly AbstractOperation Operation; + public readonly bool MustSucceed; + + public InnerOperation(AbstractOperation op, bool mustSucceed) + { + Operation = op; + MustSucceed = mustSucceed; + op.IsInnerOperation = true; + } + } + +} diff --git a/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs b/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs index 85baf8c142..f10d1bfdfb 100644 --- a/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs +++ b/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs @@ -31,7 +31,7 @@ public PackageOperation( OperationType role, bool IgnoreParallelInstalls = false, AbstractOperation? req = null) - : base(!IgnoreParallelInstalls, req) + : base(!IgnoreParallelInstalls, _getPreInstallOps(options, req), _getPostInstallOps(options)) { Package = package; Options = options; @@ -128,11 +128,38 @@ public override Task GetOperationIcon() { return TaskRecycler.RunOrAttachAsync(Package.GetIconUrl); } + + private static IReadOnlyList _getPreInstallOps(InstallOptions opts, AbstractOperation? preReq = null) + { + List l = new(); + + // Things Things Things + + if(preReq is not null) l.Add(new(preReq, true)); + return l; + } + + private static IReadOnlyList _getPostInstallOps(InstallOptions opts) + { + List l = new(); + + // Things Things Things + + return l; + } } + /* + * + * + * + * PER-OPERATION PACKAGE OPERATIONS + * + * + * + */ public class InstallPackageOperation : PackageOperation { - public InstallPackageOperation( IPackage package, InstallOptions options, diff --git a/src/UniGetUI.PackageEngine.Operations/ProcessOperation.cs b/src/UniGetUI.PackageEngine.Operations/ProcessOperation.cs index b682969f01..a31d05980e 100644 --- a/src/UniGetUI.PackageEngine.Operations/ProcessOperation.cs +++ b/src/UniGetUI.PackageEngine.Operations/ProcessOperation.cs @@ -11,7 +11,10 @@ public abstract class AbstractProcessOperation : AbstractOperation protected Process process { get; private set; } private bool ProcessKilled; - protected AbstractProcessOperation(bool queue_enabled, AbstractOperation? req) : base(queue_enabled, req) + protected AbstractProcessOperation( + bool queue_enabled, + IReadOnlyList? preOps = null, + IReadOnlyList? postOps = null) : base(queue_enabled, preOps, postOps) { process = new(); CancelRequested += (_, _) => diff --git a/src/UniGetUI/AppOperationHelper.cs b/src/UniGetUI/AppOperationHelper.cs index 4ef6f908e3..1f8aefb6f4 100644 --- a/src/UniGetUI/AppOperationHelper.cs +++ b/src/UniGetUI/AppOperationHelper.cs @@ -116,7 +116,11 @@ public static void Remove(AbstractOperation op) } /* + * + * * PACKAGE INSTALLATION + * + * */ public static async Task Install(IPackage? package, TEL_InstallReferral referral, bool? elevated = null, bool? interactive = null, bool? no_integrity = null, bool ignoreParallel = false, @@ -141,8 +145,31 @@ public static void Install(IReadOnlyList packages, TEL_InstallReferral } } + public static async Task UninstallThenReinstall(IPackage? package, TEL_InstallReferral referral) + { + if (package is null) return null; + + var options = await InstallOptionsFactory.LoadApplicableAsync(package); + + var uninstallOp = new UninstallPackageOperation(package, options); + uninstallOp.OperationSucceeded += (_, _) => TelemetryHandler.UninstallPackage(package, TEL_OP_RESULT.SUCCESS); + uninstallOp.OperationFailed += (_, _) => TelemetryHandler.UninstallPackage(package, TEL_OP_RESULT.FAILED); + + var installOp = new InstallPackageOperation(package, options, req: uninstallOp); + installOp.OperationSucceeded += (_, _) => TelemetryHandler.InstallPackage(package, TEL_OP_RESULT.SUCCESS, referral); + installOp.OperationFailed += (_, _) => TelemetryHandler.InstallPackage(package, TEL_OP_RESULT.FAILED, referral); + + Add(installOp); + Instance.MainWindow.UpdateSystemTrayStatus(); + return installOp; + } + /* + * + * * PACKAGE UPDATE + * + * */ public static async Task Update(IPackage? package, bool? elevated = null, bool? interactive = null, bool? no_integrity = null, bool ignoreParallel = false, AbstractOperation? req = null) { @@ -197,8 +224,31 @@ public static async void UpdateForId(string packageId) Logger.Warn($"[WIDGETS] No package with id={packageId} was found"); } + public static async Task UninstallThenUpdate(IPackage? package) + { + if (package is null) return null; + + var options = await InstallOptionsFactory.LoadApplicableAsync(package); + + var uninstallOp = new UninstallPackageOperation(package, options); + uninstallOp.OperationSucceeded += (_, _) => TelemetryHandler.UninstallPackage(package, TEL_OP_RESULT.SUCCESS); + uninstallOp.OperationFailed += (_, _) => TelemetryHandler.UninstallPackage(package, TEL_OP_RESULT.FAILED); + + var installOp = new UpdatePackageOperation(package, options, req: uninstallOp); + installOp.OperationSucceeded += (_, _) => TelemetryHandler.UpdatePackage(package, TEL_OP_RESULT.SUCCESS); + installOp.OperationFailed += (_, _) => TelemetryHandler.UpdatePackage(package, TEL_OP_RESULT.FAILED); + + Add(installOp); + Instance.MainWindow.UpdateSystemTrayStatus(); + return installOp; + } + /* + * + * * PACKAGE UNINSTALL + * + * */ public static async void ConfirmAndUninstall(IReadOnlyList packages, bool? elevated = null, bool? interactive = null, bool? remove_data = null) diff --git a/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs b/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs index a694c46479..d2c3a85a7f 100644 --- a/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/InstalledPackagesPage.cs @@ -426,11 +426,8 @@ private void MenuRemoveData_Invoked(object sender, RoutedEventArgs args) private void MenuReinstall_Invoked(object sender, RoutedEventArgs args) => _ = MainApp.Operations.Install(SelectedItem, TEL_InstallReferral.ALREADY_INSTALLED); - private async void MenuUninstallThenReinstall_Invoked(object sender, RoutedEventArgs args) - { - var op = await MainApp.Operations.Uninstall(SelectedItem, ignoreParallel: true); - _ = MainApp.Operations.Install(SelectedItem, TEL_InstallReferral.ALREADY_INSTALLED, ignoreParallel: true, req: op); - } + private void MenuUninstallThenReinstall_Invoked(object sender, RoutedEventArgs args) + => _ = MainApp.Operations.UninstallThenReinstall(SelectedItem, TEL_InstallReferral.ALREADY_INSTALLED); private async void MenuIgnorePackage_Invoked(object sender, RoutedEventArgs args) { diff --git a/src/UniGetUI/Pages/SoftwarePages/SoftwareUpdatesPage.cs b/src/UniGetUI/Pages/SoftwarePages/SoftwareUpdatesPage.cs index eb3f502af3..49e6263fa4 100644 --- a/src/UniGetUI/Pages/SoftwarePages/SoftwareUpdatesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/SoftwareUpdatesPage.cs @@ -494,11 +494,8 @@ private void MenuInteractive_Invoked(object sender, RoutedEventArgs e) private void MenuAsAdmin_Invoked(object sender, RoutedEventArgs e) => _ = MainApp.Operations.Update(SelectedItem, elevated: true); - private async void MenuUpdateAfterUninstall_Invoked(object sender, RoutedEventArgs e) - { - var op = await MainApp.Operations.Uninstall(SelectedItem); - _ = MainApp.Operations.Install(SelectedItem, TEL_InstallReferral.ALREADY_INSTALLED, req: op); - } + private void MenuUpdateAfterUninstall_Invoked(object sender, RoutedEventArgs e) + => _ = MainApp.Operations.UninstallThenUpdate(SelectedItem); private void MenuUninstall_Invoked(object sender, RoutedEventArgs e) => _ = MainApp.Operations.Uninstall(SelectedItem); From 4923dde03bad47828054aeb329ec5117a9283f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 17 Jun 2025 15:43:13 +0200 Subject: [PATCH 02/12] Add the option for UniGetUI to kill a process name before an operation with a package is performed --- .../AbstractOperation.cs | 3 +- ...eration.cs => AbstractProcessOperation.cs} | 0 .../KillProcessOperation.cs | 57 ++++++++++++ .../PackageOperations.cs | 7 +- .../InstallOptions.cs | 16 +++- src/UniGetUI/Controls/MenuForPackage.cs | 1 + .../DialogPages/InstallOptions_Package.xaml | 29 ++++++ .../InstallOptions_Package.xaml.cs | 91 +++++++++++++++++-- src/UniGetUI/UniGetUI.csproj | 1 + 9 files changed, 189 insertions(+), 16 deletions(-) rename src/UniGetUI.PackageEngine.Operations/{ProcessOperation.cs => AbstractProcessOperation.cs} (100%) create mode 100644 src/UniGetUI.PackageEngine.Operations/KillProcessOperation.cs diff --git a/src/UniGetUI.PackageEngine.Operations/AbstractOperation.cs b/src/UniGetUI.PackageEngine.Operations/AbstractOperation.cs index ae11c47d72..9876844968 100644 --- a/src/UniGetUI.PackageEngine.Operations/AbstractOperation.cs +++ b/src/UniGetUI.PackageEngine.Operations/AbstractOperation.cs @@ -23,7 +23,7 @@ public abstract partial class AbstractOperation : IDisposable public bool Started { get; private set; } protected bool QUEUE_ENABLED; protected bool FORCE_HOLD_QUEUE; - private bool IsInnerOperation = false; + private bool IsInnerOperation; private readonly List<(string, LineType)> LogList = []; private OperationStatus _status = OperationStatus.InQueue; @@ -38,7 +38,6 @@ public void ApplyCapabilities(bool admin, bool interactive, bool skiphash, strin BadgesChanged?.Invoke(this, new BadgeCollection(admin, interactive, skiphash, scope)); } - // private readonly AbstractOperation? requirement; private readonly IReadOnlyList PreOperations = []; private readonly IReadOnlyList PostOperations = []; diff --git a/src/UniGetUI.PackageEngine.Operations/ProcessOperation.cs b/src/UniGetUI.PackageEngine.Operations/AbstractProcessOperation.cs similarity index 100% rename from src/UniGetUI.PackageEngine.Operations/ProcessOperation.cs rename to src/UniGetUI.PackageEngine.Operations/AbstractProcessOperation.cs diff --git a/src/UniGetUI.PackageEngine.Operations/KillProcessOperation.cs b/src/UniGetUI.PackageEngine.Operations/KillProcessOperation.cs new file mode 100644 index 0000000000..43baa16b0c --- /dev/null +++ b/src/UniGetUI.PackageEngine.Operations/KillProcessOperation.cs @@ -0,0 +1,57 @@ + +using System.Diagnostics; +using UniGetUI.Core.Tools; +using UniGetUI.PackageEngine.Enums; + +namespace UniGetUI.PackageOperations; + +public class KillProcessOperation: AbstractOperation +{ + private string ProcessName; + public KillProcessOperation(string procName) : base(false) + { + ProcessName = CoreTools.MakeValidFileName(procName); + Metadata.Status = $"Closing process(es) {procName}"; + Metadata.Title = $"Closing process(es) {procName}"; + Metadata.OperationInformation = " "; + Metadata.SuccessTitle = $"Done!"; + Metadata.SuccessMessage = $"Done!"; + Metadata.FailureTitle = $"Failed to close process"; + Metadata.FailureMessage = $"The process(es) {procName} could not be closed"; + } + + protected override void ApplyRetryAction(string retryMode) + { + } + + protected override async Task PerformOperation() + { + try + { + Line($"Attempting to close all processes with name {ProcessName}...", LineType.Information); + var procs = Process.GetProcessesByName(ProcessName.Replace(".exe", "")); + foreach (var proc in procs) + { + if(proc.HasExited) continue; + Line($"Attempting to close process {ProcessName} with pid={proc.Id}...", LineType.VerboseDetails); + proc.CloseMainWindow(); + await Task.WhenAny(proc.WaitForExitAsync(), Task.Delay(1000)); + if (!proc.HasExited) + { + Line($"Timeout for process {ProcessName}, attempting to kill...", LineType.Information); + proc.Kill(); + } + } + + return OperationVeredict.Success; + } + catch (Exception ex) + { + Line(ex.ToString(), LineType.Error); + return OperationVeredict.Failure; + } + } + + public override Task GetOperationIcon() + => Task.FromResult(new Uri("about:blank")); +} diff --git a/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs b/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs index f10d1bfdfb..0416f41ee3 100644 --- a/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs +++ b/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs @@ -132,10 +132,13 @@ public override Task GetOperationIcon() private static IReadOnlyList _getPreInstallOps(InstallOptions opts, AbstractOperation? preReq = null) { List l = new(); + if(preReq is not null) l.Add(new(preReq, true)); - // Things Things Things + foreach (var process in opts.KillBeforeOperation) + l.Add(new InnerOperation( + new KillProcessOperation(process), + mustSucceed: false)); - if(preReq is not null) l.Add(new(preReq, true)); return l; } diff --git a/src/UniGetUI.PackageEngine.Serializable/InstallOptions.cs b/src/UniGetUI.PackageEngine.Serializable/InstallOptions.cs index c5311fed78..22d3207c15 100644 --- a/src/UniGetUI.PackageEngine.Serializable/InstallOptions.cs +++ b/src/UniGetUI.PackageEngine.Serializable/InstallOptions.cs @@ -19,6 +19,8 @@ public class InstallOptions: SerializableComponent public bool SkipMinorUpdates { get; set; } public bool OverridesNextLevelOpts { get; set; } public bool RemoveDataOnUninstall { get; set; } + public List KillBeforeOperation { get; set; } = []; + public override InstallOptions Copy() { @@ -27,9 +29,9 @@ public override InstallOptions Copy() SkipHashCheck = SkipHashCheck, Architecture = Architecture, CustomInstallLocation = CustomInstallLocation, - CustomParameters_Install = CustomParameters_Install, - CustomParameters_Update = CustomParameters_Update, - CustomParameters_Uninstall = CustomParameters_Uninstall, + CustomParameters_Install = CustomParameters_Install.ToList(), + CustomParameters_Update = CustomParameters_Update.ToList(), + CustomParameters_Uninstall = CustomParameters_Uninstall.ToList(), InstallationScope = InstallationScope, InteractiveInstallation = InteractiveInstallation, PreRelease = PreRelease, @@ -38,6 +40,7 @@ public override InstallOptions Copy() SkipMinorUpdates = SkipMinorUpdates, OverridesNextLevelOpts = OverridesNextLevelOpts, RemoveDataOnUninstall = RemoveDataOnUninstall, + KillBeforeOperation = KillBeforeOperation.ToList(), }; } @@ -65,6 +68,7 @@ this.CustomParameters_Uninstall.Count is 0 && this.CustomParameters_Uninstall = ReadArrayFromJson(data, "CustomParameters"); } + this.KillBeforeOperation = ReadArrayFromJson(data, nameof(KillBeforeOperation)); this.PreRelease = data[nameof(PreRelease)]?.GetVal() ?? false; this.CustomInstallLocation = data[nameof(CustomInstallLocation)]?.GetVal() ?? ""; this.Version = data[nameof(Version)]?.GetVal() ?? ""; @@ -98,6 +102,7 @@ SkipMinorUpdates is not false || CustomParameters_Install.Where(x => x != "").Any() || CustomParameters_Update.Where(x => x != "").Any() || CustomParameters_Uninstall.Where(x => x != "").Any() || + KillBeforeOperation.Where(x => x != "").Any() || CustomInstallLocation.Any() || RemoveDataOnUninstall is not false || Version.Any(); @@ -115,8 +120,8 @@ public InstallOptions(JsonNode data) : base(data) public override string ToString() { - string customparams = CustomParameters_Install.Any() ? string.Join(",", CustomParameters_Install) : "[]"; - customparams += CustomParameters_Update.Any() ? string.Join(",", CustomParameters_Update) : "[]"; + string customparams = CustomParameters_Install.Any() ? string.Join(",", CustomParameters_Install) : "[],"; + customparams += CustomParameters_Update.Any() ? string.Join(",", CustomParameters_Update) : "[],"; customparams += CustomParameters_Uninstall.Any() ? string.Join(",", CustomParameters_Uninstall) : "[]"; return $""; } } diff --git a/src/UniGetUI/Controls/MenuForPackage.cs b/src/UniGetUI/Controls/MenuForPackage.cs index c45854fa86..3bda72b84d 100644 --- a/src/UniGetUI/Controls/MenuForPackage.cs +++ b/src/UniGetUI/Controls/MenuForPackage.cs @@ -76,6 +76,7 @@ public partial class BetterTabViewItem : TabViewItem public BetterTabViewItem() { IsClosable = false; + CanDrag = false; } public void LoadText() diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml index ea6922d21d..7af1d4e75d 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml @@ -11,6 +11,16 @@ xmlns:widgets="using:UniGetUI.Interface.Widgets" MaxWidth="700" mc:Ignorable="d"> + + + + + + + + + + @@ -131,6 +141,7 @@ HorizontalAlignment="Stretch" Background="{ThemeResource SystemChromeAltHighColor}" IsAddTabButtonVisible="False" + CanReorderTabs="False" TabWidthMode="SizeToContent"> + + + + + diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs index 4f65948bd5..7c3d8f3232 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs @@ -1,5 +1,9 @@ +using System.Collections.ObjectModel; +using System.ComponentModel; using System.Data; +using System.Diagnostics; using System.Runtime.InteropServices; +using CommunityToolkit.WinUI.Controls; using Microsoft.Extensions.Options; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; @@ -13,6 +17,7 @@ using UniGetUI.PackageEngine.Serializable; using UniGetUI.Pages.SettingsPages.GeneralPages; using Windows.ApplicationModel.Activation; +using Windows.Services.Maps; using Architecture = UniGetUI.PackageEngine.Enums.Architecture; // To learn more about WinUI, the WinUI project structure, @@ -32,6 +37,10 @@ public sealed partial class InstallOptionsPage : Page private readonly string packageInstallLocation; private bool _uiLoaded; + public ObservableCollection ProcessesToKill = new(); + private readonly ObservableCollection _runningProcesses = new(); + public ObservableCollection SuggestedProcesses = new(); + public InstallOptionsPage(IPackage package, InstallOptions options) : this(package, OperationType.None, options) { } public InstallOptionsPage(IPackage package, OperationType operation, InstallOptions options) { @@ -82,6 +91,7 @@ async Task LoadImage() _ = LoadImage(); DialogTitle.Text = CoreTools.Translate("{0} installation options", package.Name); PlaceholderText.Text = CoreTools.Translate("{0} Install options are currently locked because {0} follows the default install options.", package.Name); + KillProcessesBox.PlaceholderText = CoreTools.Translate("Write here the process names, separed by commas (,)"); packageInstallLocation = Package.Manager.DetailsHelper.GetInstallLocation(package) ?? CoreTools.Translate("Unset or unknown"); @@ -154,11 +164,14 @@ async Task LoadImage() } } + foreach(var p in Options.KillBeforeOperation) + { + ProcessesToKill.Add(new(p)); + } if (Options.CustomInstallLocation == "") CustomInstallLocation.Text = packageInstallLocation; else CustomInstallLocation.Text = Options.CustomInstallLocation; - CustomParameters1.Text = string.Join(' ', Options.CustomParameters_Install); CustomParameters2.Text = string.Join(' ', Options.CustomParameters_Update); CustomParameters3.Text = string.Join(' ', Options.CustomParameters_Uninstall); @@ -166,8 +179,20 @@ async Task LoadImage() _uiLoaded = true; EnableDisableControls(operation); LoadIgnoredUpdates(); + _ = _loadProcesses(); } + private async Task _loadProcesses() + { + var processNames = await Task.Run(() => + Process.GetProcesses().Select(p => p.ProcessName).Distinct().ToList()); + + _runningProcesses.Clear(); + foreach (var name in processNames) + { + if(name.Any()) _runningProcesses.Add(new(name + ".exe")); + } + } private void EnableDisableControls(OperationType operation) { if(FollowGlobalOptionsSwitch.IsOn) @@ -188,13 +213,17 @@ private void EnableDisableControls(OperationType operation) AdminCheckBox.IsEnabled = Package.Manager.Capabilities.CanRunAsAdmin; InteractiveCheckBox.IsEnabled = Package.Manager.Capabilities.CanRunInteractively; - HashCheckbox.IsEnabled = operation != OperationType.Uninstall && Package.Manager.Capabilities.CanSkipIntegrityChecks; - ArchitectureComboBox.IsEnabled = operation != OperationType.Uninstall && Package.Manager.Capabilities.SupportsCustomArchitectures; + HashCheckbox.IsEnabled = + operation is not OperationType.Uninstall + && Package.Manager.Capabilities.CanSkipIntegrityChecks; + + ArchitectureComboBox.IsEnabled = + operation is not OperationType.Uninstall + && Package.Manager.Capabilities.SupportsCustomArchitectures; + VersionComboBox.IsEnabled = - (operation == OperationType.Install - || operation == OperationType.None) - && (Package.Manager.Capabilities.SupportsCustomVersions - || Package.Manager.Capabilities.SupportsPreRelease); + operation is OperationType.Install or OperationType.None + && (Package.Manager.Capabilities.SupportsCustomVersions || Package.Manager.Capabilities.SupportsPreRelease); ScopeCombo.IsEnabled = Package.Manager.Capabilities.SupportsCustomScopes; ResetDir.IsEnabled = Package.Manager.Capabilities.SupportsCustomLocations; SelectDir.IsEnabled = Package.Manager.Capabilities.SupportsCustomLocations; @@ -269,6 +298,9 @@ public async Task GetUpdatedOptions(bool updateIgnoredUpdates = Options.CustomParameters_Uninstall = CustomParameters3.Text.Split(' ').ToList(); Options.PreRelease = VersionComboBox.SelectedValue.ToString() == CoreTools.Translate("PreRelease"); + Options.KillBeforeOperation.Clear(); + foreach(var p in ProcessesToKill) Options.KillBeforeOperation.Add(p.Name); + if (VersionComboBox.SelectedValue.ToString() != CoreTools.Translate("PreRelease") && VersionComboBox.SelectedValue.ToString() != CoreTools.Translate("Latest")) { Options.Version = VersionComboBox.SelectedValue.ToString() ?? ""; @@ -363,5 +395,50 @@ private void GoToSecureSettings_Click(object sender, RoutedEventArgs e) Close?.Invoke(this, EventArgs.Empty); MainApp.Instance.MainWindow.NavigationPage.OpenSettingsPage(typeof(Administrator)); } + + private void KillProcessesBox_TokenItemAdding(TokenizingTextBox sender, TokenItemAddingEventArgs args) + { + args.Item = _runningProcesses.FirstOrDefault((item) => item.Name.Contains(args.TokenText)); + if(args.Item is null) + { + string text = args.TokenText; + if (!text.EndsWith(".exe")) text += ".exe"; + args.Item = new IOP_Proc(text); + } + } + + private async void KillProcessesBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) + { + var text = KillProcessesBox.Text; + await Task.Delay(100); + if (text != KillProcessesBox.Text) + return; + + SuggestedProcesses.Clear(); + if (text.Trim() != "") + { + if (!text.EndsWith(".exe")) + text = text.Trim() + ".exe"; + SuggestedProcesses.Add(new(text)); + foreach (var item in _runningProcesses.Where(x => x.Name.Contains(KillProcessesBox.Text))) + { + SuggestedProcesses.Add(item); + } + } + } + + private void KillProcessesBox_Loaded(object sender, RoutedEventArgs e) + { + + } + } + + public class IOP_Proc + { + public readonly string Name; + public IOP_Proc(string name) + { + Name = name; + } } } diff --git a/src/UniGetUI/UniGetUI.csproj b/src/UniGetUI/UniGetUI.csproj index 9a3c1c3188..8da2b149ac 100644 --- a/src/UniGetUI/UniGetUI.csproj +++ b/src/UniGetUI/UniGetUI.csproj @@ -73,6 +73,7 @@ + From 63f0af713de5efe48f8f92a2ff7192f5bfa0f43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 17 Jun 2025 17:20:27 +0200 Subject: [PATCH 03/12] Layout improvements to Package Install Options UI --- .../SettingsEngine_Names.cs | 2 + .../KillProcessOperation.cs | 12 ++++- .../Controls/SettingsWidgets/CheckboxCard.cs | 6 +++ .../DialogPages/InstallOptions_Package.xaml | 52 ++++++++++++------- .../InstallOptions_Package.xaml.cs | 17 ++++-- .../GeneralPages/Operations.xaml | 9 ++++ 6 files changed, 71 insertions(+), 27 deletions(-) diff --git a/src/UniGetUI.Core.Settings/SettingsEngine_Names.cs b/src/UniGetUI.Core.Settings/SettingsEngine_Names.cs index e9a5054fea..33a55de508 100644 --- a/src/UniGetUI.Core.Settings/SettingsEngine_Names.cs +++ b/src/UniGetUI.Core.Settings/SettingsEngine_Names.cs @@ -74,6 +74,7 @@ public enum K DisableErrorNotifications, DisableSuccessNotifications, DisableProgressNotifications, + KillProcessesThatRefuseToDie, Test1, Test2, @@ -159,6 +160,7 @@ public static string ResolveKey(K key) K.DisableErrorNotifications => "DisableErrorNotifications", K.DisableSuccessNotifications => "DisableSuccessNotifications", K.DisableProgressNotifications => "DisableProgressNotifications", + K.KillProcessesThatRefuseToDie => "KillProcessesThatRefuseToDie", K.Test1 => "TestSetting1", K.Test2 => "TestSetting2", diff --git a/src/UniGetUI.PackageEngine.Operations/KillProcessOperation.cs b/src/UniGetUI.PackageEngine.Operations/KillProcessOperation.cs index 43baa16b0c..6f9582f653 100644 --- a/src/UniGetUI.PackageEngine.Operations/KillProcessOperation.cs +++ b/src/UniGetUI.PackageEngine.Operations/KillProcessOperation.cs @@ -1,5 +1,6 @@ using System.Diagnostics; +using UniGetUI.Core.SettingsEngine; using UniGetUI.Core.Tools; using UniGetUI.PackageEngine.Enums; @@ -38,8 +39,15 @@ protected override async Task PerformOperation() await Task.WhenAny(proc.WaitForExitAsync(), Task.Delay(1000)); if (!proc.HasExited) { - Line($"Timeout for process {ProcessName}, attempting to kill...", LineType.Information); - proc.Kill(); + if(Settings.Get(Settings.K.KillProcessesThatRefuseToDie)) + { + Line($"Timeout for process {ProcessName}, attempting to kill...", LineType.Information); + proc.Kill(); + } + else + { + Line($"{ProcessName} with pid={proc.Id} did not exit and will not be killed. You can change this from UniGetUI settings.", LineType.Error); + } } } diff --git a/src/UniGetUI/Controls/SettingsWidgets/CheckboxCard.cs b/src/UniGetUI/Controls/SettingsWidgets/CheckboxCard.cs index 81cd186a8f..f2356409d7 100644 --- a/src/UniGetUI/Controls/SettingsWidgets/CheckboxCard.cs +++ b/src/UniGetUI/Controls/SettingsWidgets/CheckboxCard.cs @@ -56,6 +56,11 @@ public Brush WarningForeground set => _warningBlock.Foreground = value; } + public double WarningOpacity + { + set => _warningBlock.Opacity = value; + } + public CheckboxCard() { _checkbox = new ToggleSwitch() @@ -74,6 +79,7 @@ public CheckboxCard() Margin = new Thickness(0, 0, 0, 0), TextWrapping = TextWrapping.Wrap, FontSize = 12, + Opacity = 0.7, Visibility = Visibility.Collapsed, }; IS_INVERTED = false; diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml index 7af1d4e75d..70a12fa9c3 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml @@ -140,8 +140,8 @@ x:Name="SettingsTabBar" HorizontalAlignment="Stretch" Background="{ThemeResource SystemChromeAltHighColor}" - IsAddTabButtonVisible="False" CanReorderTabs="False" + IsAddTabButtonVisible="False" TabWidthMode="SizeToContent"> + - - - - - @@ -322,6 +308,32 @@ + + + + + + + + + + + GetUpdatedOptions(bool updateIgnoredUpdates = true) + public async Task GetUpdatedOptions(bool updateDetachedOptions = true) { Options.RunAsAdministrator = AdminCheckBox?.IsChecked ?? false; Options.InteractiveInstallation = InteractiveCheckBox?.IsChecked ?? false; @@ -311,8 +316,10 @@ public async Task GetUpdatedOptions(bool updateIgnoredUpdates = } Options.SkipMinorUpdates = SkipMinorUpdatesCheckbox?.IsChecked ?? false; - if (updateIgnoredUpdates) + if (updateDetachedOptions) { + Settings.Set(Settings.K.KillProcessesThatRefuseToDie, KillProcessesThatWontDie.IsChecked ?? false); + if (IgnoreUpdatesCheckbox?.IsChecked ?? false) { await Package.AddToIgnoredUpdatesAsync(version: "*"); @@ -361,7 +368,7 @@ private void CloseButton_Click(object sender, RoutedEventArgs e) private async void GenerateCommand() { if (!_uiLoaded) return; - InstallOptions options = await GetUpdatedOptions(updateIgnoredUpdates: false); + InstallOptions options = await GetUpdatedOptions(updateDetachedOptions: false); options = await InstallOptionsFactory.LoadApplicableAsync(this.Package, overridePackageOptions: options); var op = ProfileComboBox.SelectedIndex switch diff --git a/src/UniGetUI/Pages/SettingsPages/GeneralPages/Operations.xaml b/src/UniGetUI/Pages/SettingsPages/GeneralPages/Operations.xaml index 8d0ff4d959..493123dd08 100644 --- a/src/UniGetUI/Pages/SettingsPages/GeneralPages/Operations.xaml +++ b/src/UniGetUI/Pages/SettingsPages/GeneralPages/Operations.xaml @@ -40,6 +40,15 @@ SettingName="MaintainSuccessfulInstalls" Text="Clear successful operations from the operation list after a 5 second delay" /> + + + Date: Tue, 17 Jun 2025 17:59:25 +0200 Subject: [PATCH 04/12] Update InstallOptions_Package.xaml.cs --- .../Pages/DialogPages/InstallOptions_Package.xaml.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs index ecb4b4fbc0..4a8ae178f9 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs @@ -44,7 +44,7 @@ public sealed partial class InstallOptionsPage : Page public InstallOptionsPage(IPackage package, InstallOptions options) : this(package, OperationType.None, options) { } public InstallOptionsPage(IPackage package, OperationType operation, InstallOptions options) - { + { Package = package; InitializeComponent(); Operation = operation; @@ -267,10 +267,8 @@ private async Task LoadVersions() } VersionComboBox.IsEnabled = - (Operation == OperationType.Install - || Operation == OperationType.None) - && (Package.Manager.Capabilities.SupportsCustomVersions - || Package.Manager.Capabilities.SupportsPreRelease); + Operation is OperationType.Install or OperationType.None + && (Package.Manager.Capabilities.SupportsCustomVersions || Package.Manager.Capabilities.SupportsPreRelease); VersionProgress.Visibility = Visibility.Collapsed; } From bc8cc7909d39beb6f555e5ddb20c93a749f4f26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Tue, 17 Jun 2025 18:30:59 +0200 Subject: [PATCH 05/12] Add animations to Package Install Options UI --- .../DialogPages/InstallOptions_Package.xaml | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml index 70a12fa9c3..efc9742bfd 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml @@ -3,6 +3,7 @@ x:Class="UniGetUI.Interface.Dialogs.InstallOptionsPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:animations="using:CommunityToolkit.WinUI.Animations" xmlns:controls="using:CommunityToolkit.WinUI.Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="using:UniGetUI.Interface.Dialogs" @@ -180,6 +181,16 @@ + + + + @@ -232,6 +243,16 @@ + + + + @@ -308,7 +329,18 @@ - + + + + + + + + + + Date: Wed, 18 Jun 2025 23:17:02 +0200 Subject: [PATCH 06/12] Add the required controls to InstallOptions_package to be able to add pre/post commands --- .../DialogPages/InstallOptions_Package.xaml | 191 ++++++++++++++++-- .../InstallOptions_Package.xaml.cs | 26 +++ .../GeneralPages/Administrator.xaml | 16 +- 3 files changed, 211 insertions(+), 22 deletions(-) diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml index efc9742bfd..a8ca9c6843 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml @@ -143,6 +143,7 @@ Background="{ThemeResource SystemChromeAltHighColor}" CanReorderTabs="False" IsAddTabButtonVisible="False" + SelectionChanged="SettingsTabBar_SelectionChanged" TabWidthMode="SizeToContent"> + - + Line2="Post-install" /> @@ -327,8 +326,8 @@ - - + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -488,6 +654,7 @@ - + WarningText="Pre and post install commands will be run before and after a package gets installed, upgraded or uninstalled. Be aware that they may break things unless used carefully" /> - + WarningText="Pre and post install commands can do very nasty things to your device, if designed to do so. It can be very dangerous to import the commands from a bundle, unless you trust the source of that package bundle" /> From 7b3e2e8875e990ec328d0b7ed8945029ab8d2c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Wed, 18 Jun 2025 23:44:58 +0200 Subject: [PATCH 07/12] Implement actual PrePost commands to be saved on InstallOptions --- .../Packages/Classes/InstallOptionsFactory.cs | 39 +++++++++++++ .../InstallOptions.cs | 57 +++++++++++++++++-- .../DialogPages/InstallOptions_Package.xaml | 14 +++-- .../InstallOptions_Package.xaml.cs | 20 +++++++ 4 files changed, 121 insertions(+), 9 deletions(-) diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallOptionsFactory.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallOptionsFactory.cs index f3b4254d7b..c34e424aaf 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallOptionsFactory.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallOptionsFactory.cs @@ -223,6 +223,45 @@ private static InstallOptions EnsureSecureOptions(InstallOptions options) options.CustomParameters_Uninstall = []; } + if (!SecureSettings.Get(SecureSettings.K.AllowPrePostOpCommand)) + { + if (options.PreInstallCommand.Any()) + { + Logger.Warn($"Pre-install command {options.PreInstallCommand} will be discarded"); + options.PreInstallCommand = ""; + } + + if (options.PostInstallCommand.Any()) + { + Logger.Warn($"Post-install command {options.PostInstallCommand} will be discarded"); + options.PostInstallCommand = ""; + } + + if (options.PreUpdateCommand.Any()) + { + Logger.Warn($"Pre-update command {options.PreUpdateCommand} will be discarded"); + options.PreUpdateCommand = ""; + } + + if (options.PostUpdateCommand.Any()) + { + Logger.Warn($"Post-update command {options.PostUpdateCommand} will be discarded"); + options.PostUpdateCommand = ""; + } + + if (options.PreUninstallCommand.Any()) + { + Logger.Warn($"Pre-uninstall command {options.PreUninstallCommand} will be discarded"); + options.PreUninstallCommand = ""; + } + + if (options.PostUninstallCommand.Any()) + { + Logger.Warn($"Post-uninstall command {options.PostUninstallCommand} will be discarded"); + options.PostUninstallCommand = ""; + } + } + return options; } } diff --git a/src/UniGetUI.PackageEngine.Serializable/InstallOptions.cs b/src/UniGetUI.PackageEngine.Serializable/InstallOptions.cs index 22d3207c15..d779487782 100644 --- a/src/UniGetUI.PackageEngine.Serializable/InstallOptions.cs +++ b/src/UniGetUI.PackageEngine.Serializable/InstallOptions.cs @@ -21,6 +21,16 @@ public class InstallOptions: SerializableComponent public bool RemoveDataOnUninstall { get; set; } public List KillBeforeOperation { get; set; } = []; + public string PreInstallCommand { get; set; } = ""; + public string PostInstallCommand { get; set; } = ""; + public bool AbortOnPreInstallFail { get; set; } = true; + public string PreUpdateCommand { get; set; } = ""; + public string PostUpdateCommand { get; set; } = ""; + public bool AbortOnPreUpdateFail { get; set; } = true; + public string PreUninstallCommand { get; set; } = ""; + public string PostUninstallCommand { get; set; } = ""; + public bool AbortOnPreUninstallFail { get; set; } = true; + public override InstallOptions Copy() { @@ -41,6 +51,15 @@ public override InstallOptions Copy() OverridesNextLevelOpts = OverridesNextLevelOpts, RemoveDataOnUninstall = RemoveDataOnUninstall, KillBeforeOperation = KillBeforeOperation.ToList(), + PreInstallCommand = PreInstallCommand, + PreUpdateCommand = PreUpdateCommand, + PreUninstallCommand = PreUninstallCommand, + PostInstallCommand = PostInstallCommand, + PostUpdateCommand = PostUpdateCommand, + PostUninstallCommand = PostUninstallCommand, + AbortOnPreInstallFail = AbortOnPreInstallFail, + AbortOnPreUpdateFail = AbortOnPreUpdateFail, + AbortOnPreUninstallFail = AbortOnPreUninstallFail }; } @@ -74,6 +93,16 @@ this.CustomParameters_Uninstall.Count is 0 && this.Version = data[nameof(Version)]?.GetVal() ?? ""; this.SkipMinorUpdates = data[nameof(SkipMinorUpdates)]?.GetVal() ?? false; + this.PreInstallCommand = data[nameof(PreInstallCommand)]?.GetVal() ?? ""; + this.PreUpdateCommand = data[nameof(PreUpdateCommand)]?.GetVal() ?? ""; + this.PreUninstallCommand = data[nameof(PreUninstallCommand)]?.GetVal() ?? ""; + this.PostInstallCommand = data[nameof(PostInstallCommand)]?.GetVal() ?? ""; + this.PostUpdateCommand = data[nameof(PostUpdateCommand)]?.GetVal() ?? ""; + this.PostUninstallCommand = data[nameof(PostUninstallCommand)]?.GetVal() ?? ""; + this.AbortOnPreInstallFail = data[nameof(AbortOnPreInstallFail)]?.GetVal() ?? true; + this.AbortOnPreUpdateFail = data[nameof(AbortOnPreUpdateFail)]?.GetVal() ?? true; + this.AbortOnPreUninstallFail = data[nameof(AbortOnPreUninstallFail)]?.GetVal() ?? true; + // if OverridesNextLevelOpts is not found on the JSON, set it to true or false depending // on whether the current settings instances are different from the default values. // This entry shall be checked the last one, to ensure all other properties are set @@ -99,13 +128,22 @@ PreRelease is not false || SkipMinorUpdates is not false || Architecture.Any() || InstallationScope.Any() || - CustomParameters_Install.Where(x => x != "").Any() || - CustomParameters_Update.Where(x => x != "").Any() || - CustomParameters_Uninstall.Where(x => x != "").Any() || - KillBeforeOperation.Where(x => x != "").Any() || + CustomParameters_Install.Where(x => x.Any()).Any() || + CustomParameters_Update.Where(x => x.Any()).Any() || + CustomParameters_Uninstall.Where(x => x.Any()).Any() || + KillBeforeOperation.Where(x => x.Any()).Any() || CustomInstallLocation.Any() || RemoveDataOnUninstall is not false || - Version.Any(); + Version.Any() || + PreInstallCommand.Any() || + PostInstallCommand.Any() || + AbortOnPreInstallFail is not true || + PreUpdateCommand.Any() || + PostUpdateCommand.Any() || + AbortOnPreUpdateFail is not true || + PreUninstallCommand.Any() || + PostUninstallCommand.Any() || + AbortOnPreUninstallFail is not true; // OverridesNextLevelOpts does not need to be checked here, since // this method is invoked before this property has been set } @@ -133,6 +171,15 @@ public override string ToString() $"CustomParameters={customparams};" + $"RemoveDataOnUninstall={RemoveDataOnUninstall};" + $"KillBeforeOperation={KillBeforeOperation};" + + $"PreInstallCommand={PreInstallCommand};" + + $"PostInstallCommand={PostInstallCommand};" + + $"AbortOnPreInstallFail={AbortOnPreInstallFail};" + + $"PreUpdateCommand={PreUpdateCommand};" + + $"PostUpdateCommand={PostUpdateCommand};" + + $"AbortOnPreUpdateFail={AbortOnPreUpdateFail};" + + $"PreUninstallCommand={PreUninstallCommand};" + + $"PostUninstallCommand={PostUninstallCommand};" + + $"AbortOnPreUninstallFail={AbortOnPreUninstallFail};" + $"PreRelease={PreRelease}>"; } } diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml index a8ca9c6843..de276ac5a8 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml @@ -201,7 +201,10 @@ - + @@ -252,7 +255,7 @@ To="1.0" Duration="0:0:0.3" /> - + @@ -269,7 +272,10 @@ SelectedIndex="0" SelectionChanged="ArchitectureComboBox_SelectionChanged" /> - + @@ -285,7 +291,7 @@ VerticalAlignment="Center" SelectionChanged="ScopeCombo_SelectionChanged" /> - + diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs index 1278f3e827..ddd9f9dfd4 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs @@ -181,6 +181,16 @@ async Task LoadImage() CustomParameters2.Text = string.Join(' ', Options.CustomParameters_Update); CustomParameters3.Text = string.Join(' ', Options.CustomParameters_Uninstall); + PreInstallCommandBox.Text = Options.PreInstallCommand; + PostInstallCommandBox.Text = Options.PostInstallCommand; + PreUpdateCommandBox.Text = Options.PreUpdateCommand; + PostUpdateCommandBox.Text = Options.PostUpdateCommand; + PreUninstallCommandBox.Text = Options.PreUninstallCommand; + PostUninstallCommandBox.Text = Options.PostUninstallCommand; + AbortInsFailedCheck.IsChecked = Options.AbortOnPreInstallFail; + AbortUpdFailedCheck.IsChecked = Options.AbortOnPreUpdateFail; + AbortUniFailedCheck.IsChecked = Options.AbortOnPreUninstallFail; + _uiLoaded = true; EnableDisableControls(operation); LoadIgnoredUpdates(); @@ -322,6 +332,16 @@ public async Task GetUpdatedOptions(bool updateDetachedOptions = Options.CustomParameters_Uninstall = CustomParameters3.Text.Split(' ').ToList(); Options.PreRelease = VersionComboBox.SelectedValue.ToString() == CoreTools.Translate("PreRelease"); + Options.PreInstallCommand = PreInstallCommandBox.Text; + Options.PostInstallCommand = PostInstallCommandBox.Text; + Options.PreUpdateCommand = PreUpdateCommandBox.Text; + Options.PostUpdateCommand = PostUpdateCommandBox.Text; + Options.PreUninstallCommand = PreUninstallCommandBox.Text; + Options.PostUninstallCommand = PostUninstallCommandBox.Text; + Options.AbortOnPreInstallFail = AbortInsFailedCheck.IsChecked ?? true; + Options.AbortOnPreUpdateFail = AbortUpdFailedCheck.IsChecked ?? true; + Options.AbortOnPreUninstallFail = AbortUniFailedCheck.IsChecked ?? true; + Options.KillBeforeOperation.Clear(); foreach(var p in ProcessesToKill) Options.KillBeforeOperation.Add(p.Name); From dec23930b218456cf86373d55f118523382e470b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Wed, 18 Jun 2025 23:47:25 +0200 Subject: [PATCH 08/12] Update InstallOptionsFactory.cs --- .../Packages/Classes/InstallOptionsFactory.cs | 48 +++++-------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallOptionsFactory.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallOptionsFactory.cs index c34e424aaf..871fd8dce2 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallOptionsFactory.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Packages/Classes/InstallOptionsFactory.cs @@ -225,41 +225,19 @@ private static InstallOptions EnsureSecureOptions(InstallOptions options) if (!SecureSettings.Get(SecureSettings.K.AllowPrePostOpCommand)) { - if (options.PreInstallCommand.Any()) - { - Logger.Warn($"Pre-install command {options.PreInstallCommand} will be discarded"); - options.PreInstallCommand = ""; - } - - if (options.PostInstallCommand.Any()) - { - Logger.Warn($"Post-install command {options.PostInstallCommand} will be discarded"); - options.PostInstallCommand = ""; - } - - if (options.PreUpdateCommand.Any()) - { - Logger.Warn($"Pre-update command {options.PreUpdateCommand} will be discarded"); - options.PreUpdateCommand = ""; - } - - if (options.PostUpdateCommand.Any()) - { - Logger.Warn($"Post-update command {options.PostUpdateCommand} will be discarded"); - options.PostUpdateCommand = ""; - } - - if (options.PreUninstallCommand.Any()) - { - Logger.Warn($"Pre-uninstall command {options.PreUninstallCommand} will be discarded"); - options.PreUninstallCommand = ""; - } - - if (options.PostUninstallCommand.Any()) - { - Logger.Warn($"Post-uninstall command {options.PostUninstallCommand} will be discarded"); - options.PostUninstallCommand = ""; - } + if (options.PreInstallCommand.Any()) Logger.Warn($"Pre-install command {options.PreInstallCommand} will be discarded"); + if (options.PostInstallCommand.Any()) Logger.Warn($"Post-install command {options.PostInstallCommand} will be discarded"); + if (options.PreUpdateCommand.Any()) Logger.Warn($"Pre-update command {options.PreUpdateCommand} will be discarded"); + if (options.PostUpdateCommand.Any()) Logger.Warn($"Post-update command {options.PostUpdateCommand} will be discarded"); + if (options.PreUninstallCommand.Any()) Logger.Warn($"Pre-uninstall command {options.PreUninstallCommand} will be discarded"); + if (options.PostUninstallCommand.Any()) Logger.Warn($"Post-uninstall command {options.PostUninstallCommand} will be discarded"); + + options.PreInstallCommand = ""; + options.PostInstallCommand = ""; + options.PreUpdateCommand = ""; + options.PostUpdateCommand = ""; + options.PreUninstallCommand = ""; + options.PostUninstallCommand = ""; } return options; From 4a29b0a3333e6c638d5ffcb3aa94302b2d875fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Thu, 19 Jun 2025 00:16:09 +0200 Subject: [PATCH 09/12] Run the pre-install and post-install operations when installing, upgrading or uninstalling a package --- .../PackageOperations.cs | 21 +++++-- .../PrePostOperation.cs | 63 +++++++++++++++++++ 2 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 src/UniGetUI.PackageEngine.Operations/PrePostOperation.cs diff --git a/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs b/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs index 0416f41ee3..4970b69944 100644 --- a/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs +++ b/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs @@ -1,3 +1,4 @@ +using System.Runtime.CompilerServices; using UniGetUI.Core.Classes; using UniGetUI.Core.Data; using UniGetUI.Core.SettingsEngine; @@ -31,7 +32,7 @@ public PackageOperation( OperationType role, bool IgnoreParallelInstalls = false, AbstractOperation? req = null) - : base(!IgnoreParallelInstalls, _getPreInstallOps(options, req), _getPostInstallOps(options)) + : base(!IgnoreParallelInstalls, _getPreInstallOps(options, role, req), _getPostInstallOps(options, role)) { Package = package; Options = options; @@ -129,7 +130,7 @@ public override Task GetOperationIcon() return TaskRecycler.RunOrAttachAsync(Package.GetIconUrl); } - private static IReadOnlyList _getPreInstallOps(InstallOptions opts, AbstractOperation? preReq = null) + private static IReadOnlyList _getPreInstallOps(InstallOptions opts, OperationType role, AbstractOperation? preReq = null) { List l = new(); if(preReq is not null) l.Add(new(preReq, true)); @@ -139,14 +140,26 @@ private static IReadOnlyList _getPreInstallOps(InstallOptions op new KillProcessOperation(process), mustSucceed: false)); + if (role is OperationType.Install && opts.PreInstallCommand.Any()) + l.Add(new(new PrePostOperation(opts.PreInstallCommand), opts.AbortOnPreInstallFail)); + else if (role is OperationType.Update && opts.PreUpdateCommand.Any()) + l.Add(new(new PrePostOperation(opts.PreUpdateCommand), opts.AbortOnPreUpdateFail)); + else if (role is OperationType.Uninstall && opts.PreUninstallCommand.Any()) + l.Add(new(new PrePostOperation(opts.PreUninstallCommand), opts.AbortOnPreUninstallFail)); + return l; } - private static IReadOnlyList _getPostInstallOps(InstallOptions opts) + private static IReadOnlyList _getPostInstallOps(InstallOptions opts, OperationType role) { List l = new(); - // Things Things Things + if (role is OperationType.Install && opts.PostInstallCommand.Any()) + l.Add(new(new PrePostOperation(opts.PostInstallCommand), false)); + else if (role is OperationType.Update && opts.PostUpdateCommand.Any()) + l.Add(new(new PrePostOperation(opts.PostUpdateCommand), false)); + else if (role is OperationType.Uninstall && opts.PostUninstallCommand.Any()) + l.Add(new(new PrePostOperation(opts.PostUninstallCommand), false)); return l; } diff --git a/src/UniGetUI.PackageEngine.Operations/PrePostOperation.cs b/src/UniGetUI.PackageEngine.Operations/PrePostOperation.cs new file mode 100644 index 0000000000..d806f4dba0 --- /dev/null +++ b/src/UniGetUI.PackageEngine.Operations/PrePostOperation.cs @@ -0,0 +1,63 @@ +using UniGetUI.PackageEngine.Enums; +using UniGetUI.PackageOperations; + +namespace UniGetUI.PackageEngine.Operations; + +public class PrePostOperation : AbstractOperation +{ + private string Payload; + public PrePostOperation(string payload) : base(true) + { + Payload = payload.Replace("\r", "\n").Replace("\n\n", "\n").Replace("\n", "&"); + Metadata.Status = $"Running custom operation {Payload}"; + Metadata.Title = $"Custom operation"; + Metadata.OperationInformation = " "; + Metadata.SuccessTitle = $"Done!"; + Metadata.SuccessMessage = $"Done!"; + Metadata.FailureTitle = $"Custom operation failed"; + Metadata.FailureMessage = $"The custom operation {Payload} failed to run"; + + } + + protected override void ApplyRetryAction(string retryMode) + { + } + + protected override async Task PerformOperation() + { + Line($"Running command {Payload}", LineType.Information); + var process = new System.Diagnostics.Process + { + StartInfo = new System.Diagnostics.ProcessStartInfo + { + FileName = "cmd.exe", + Arguments = $"/C {Payload}", + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + } + }; + + process.Start(); + process.BeginErrorReadLine(); + process.BeginOutputReadLine(); + process.OutputDataReceived += (s, e) => + { + if (e.Data is not null) Line(e.Data, LineType.Information); + }; + process.ErrorDataReceived += (s, e) => + { + if (e.Data is not null) Line(e.Data, LineType.Error); + }; + await process.WaitForExitAsync(); + + int exitCode = process.ExitCode; + Line($"Exit code is {exitCode}", LineType.Information); + return (exitCode == 0 ? OperationVeredict.Success : OperationVeredict.Failure); + } + + public override Task GetOperationIcon() + => Task.FromResult(new Uri("about:blank")); + +} From cc003b45b2c7e46c1b637309548c380deffcf014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Thu, 19 Jun 2025 00:27:34 +0200 Subject: [PATCH 10/12] Only import commands when allowed to --- .../Pages/SoftwarePages/PackageBundlesPage.cs | 87 +++++++++++++------ 1 file changed, 61 insertions(+), 26 deletions(-) diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index 712128aab4..962408b591 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -665,46 +665,81 @@ public async Task AddFromBundle(string content, BundleFormatType format) SecureSettings.Get(SecureSettings.K.AllowCLIArguments) && SecureSettings.Get(SecureSettings.K.AllowImportingCLIArguments); + bool AllowPrePostOps = + SecureSettings.Get(SecureSettings.K.AllowPrePostOpCommand) && + SecureSettings.Get(SecureSettings.K.AllowImportPrePostOpCommands); + foreach (var pkg in DeserializedData.packages) { - if (pkg.InstallationOptions.CustomParameters_Install.Where(x => x.Any()).Any()) + var opts = pkg.InstallationOptions; + + if (opts.CustomParameters_Install.Where(x => x.Any()).Any()) { showReport = true; - if (!packageReport.ContainsKey(pkg.Id)) - packageReport[pkg.Id] = new(); - - packageReport[pkg.Id].Add(new( - $"Custom install arguments: [{string.Join(", ", pkg.InstallationOptions.CustomParameters_Install)}]", - AllowCLIParameters)); - - if(!AllowCLIParameters) pkg.InstallationOptions.CustomParameters_Install.Clear(); + if (!packageReport.ContainsKey(pkg.Id)) packageReport[pkg.Id] = new(); + packageReport[pkg.Id].Add(new($"Custom install arguments: [{string.Join(", ", opts.CustomParameters_Install)}]", AllowCLIParameters)); + if(!AllowCLIParameters) opts.CustomParameters_Install.Clear(); } - if (pkg.InstallationOptions.CustomParameters_Update.Where(x => x.Any()).Any()) + if (opts.CustomParameters_Update.Where(x => x.Any()).Any()) { showReport = true; - if (!packageReport.ContainsKey(pkg.Id)) - packageReport[pkg.Id] = new(); - - packageReport[pkg.Id].Add(new( - $"Custom update arguments: [{string.Join(", ", pkg.InstallationOptions.CustomParameters_Update)}]", - AllowCLIParameters)); - - if(!AllowCLIParameters) pkg.InstallationOptions.CustomParameters_Update.Clear(); + if (!packageReport.ContainsKey(pkg.Id)) packageReport[pkg.Id] = new(); + packageReport[pkg.Id].Add(new($"Custom update arguments: [{string.Join(", ", opts.CustomParameters_Update)}]", AllowCLIParameters)); + if(!AllowCLIParameters) opts.CustomParameters_Update.Clear(); } - if (pkg.InstallationOptions.CustomParameters_Uninstall.Where(x => x.Any()).Any()) + if (opts.CustomParameters_Uninstall.Where(x => x.Any()).Any()) { showReport = true; - if (!packageReport.ContainsKey(pkg.Id)) - packageReport[pkg.Id] = new(); - - packageReport[pkg.Id].Add(new( - $"Custom uninstall arguments: [{string.Join(", ", pkg.InstallationOptions.CustomParameters_Uninstall)}]", - AllowCLIParameters)); + if (!packageReport.ContainsKey(pkg.Id)) packageReport[pkg.Id] = new(); + packageReport[pkg.Id].Add(new($"Custom uninstall arguments: [{string.Join(", ", opts.CustomParameters_Uninstall)}]", AllowCLIParameters)); + if(!AllowCLIParameters) opts.CustomParameters_Uninstall.Clear(); + } - if(!AllowCLIParameters) pkg.InstallationOptions.CustomParameters_Uninstall.Clear(); + if (opts.PreInstallCommand.Any()) + { + showReport = true; + if (!packageReport.ContainsKey(pkg.Id)) packageReport[pkg.Id] = new(); + packageReport[pkg.Id].Add(new($"Pre-install command: {opts.PreInstallCommand}", AllowPrePostOps)); + if (!AllowPrePostOps) opts.PreInstallCommand = ""; + } + if (opts.PostInstallCommand.Any()) + { + showReport = true; + if (!packageReport.ContainsKey(pkg.Id)) packageReport[pkg.Id] = new(); + packageReport[pkg.Id].Add(new($"Post-install command: {opts.PostInstallCommand}", AllowPrePostOps)); + if (!AllowPrePostOps) opts.PostInstallCommand = ""; + } + if (opts.PreUpdateCommand.Any()) + { + showReport = true; + if (!packageReport.ContainsKey(pkg.Id)) packageReport[pkg.Id] = new(); + packageReport[pkg.Id].Add(new($"Pre-update command: {opts.PreUpdateCommand}", AllowPrePostOps)); + if (!AllowPrePostOps) opts.PreUpdateCommand = ""; + } + if (opts.PostUpdateCommand.Any()) + { + showReport = true; + if (!packageReport.ContainsKey(pkg.Id)) packageReport[pkg.Id] = new(); + packageReport[pkg.Id].Add(new($"Post-update command: {opts.PostUpdateCommand}", AllowPrePostOps)); + if (!AllowPrePostOps) opts.PostUpdateCommand = ""; + } + if (opts.PreUninstallCommand.Any()) + { + showReport = true; + if (!packageReport.ContainsKey(pkg.Id)) packageReport[pkg.Id] = new(); + packageReport[pkg.Id].Add(new($"Pre-uninstall command: {opts.PreUninstallCommand}", AllowPrePostOps)); + if (!AllowPrePostOps) opts.PreUninstallCommand = ""; + } + if (opts.PostUninstallCommand.Any()) + { + showReport = true; + if (!packageReport.ContainsKey(pkg.Id)) packageReport[pkg.Id] = new(); + packageReport[pkg.Id].Add(new($"Post-uninstall command: {opts.PostUninstallCommand}", AllowPrePostOps)); + if (!AllowPrePostOps) opts.PostUninstallCommand = ""; } + pkg.InstallationOptions = opts; packages.Add(DeserializePackage(pkg)); } From 4db9e55960a379c264a69e6b669ee5828f753835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Fri, 20 Jun 2025 12:07:21 +0200 Subject: [PATCH 11/12] clean up unneeded imports --- src/UniGetUI.Core.Data/CoreData.cs | 3 --- src/UniGetUI.Core.LanguageEngine/LanguageData.cs | 2 -- src/UniGetUI.Core.SecureSettings/SecureSettings.cs | 2 -- src/UniGetUI.Core.Tools/SerializationHelpers.cs | 1 - src/UniGetUI.PackageEngine.Enums/ManagerCapabilities.cs | 2 -- .../OverridenInstallationOptions.cs | 2 -- .../Chocolatey.cs | 1 - .../Helpers/ChocolateyPkgOperationHelper.cs | 1 - src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs | 1 - .../Helpers/DotNetPkgOperationHelper.cs | 1 - .../Helpers/ScoopPkgOperationHelper.cs | 1 - src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs | 1 - .../ClientHelpers/NativePackageHandler.cs | 2 -- .../ClientHelpers/WinGetIconsHelper.cs | 2 -- .../Helpers/WinGetPkgDetailsHelper.cs | 2 -- .../Helpers/WinGetPkgOperationHelper.cs | 2 -- src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs | 2 -- src/UniGetUI.PackageEngine.Operations/AbstractOperation.cs | 1 - src/UniGetUI/App.xaml.cs | 1 - src/UniGetUI/CrashHandler.cs | 2 -- src/UniGetUI/EntryPoint.cs | 1 - src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml | 1 - .../Pages/DialogPages/InstallOptions_Package.xaml.cs | 7 +------ .../Pages/SoftwarePages/AbstractPackagesPage.xaml.cs | 1 - 24 files changed, 1 insertion(+), 41 deletions(-) diff --git a/src/UniGetUI.Core.Data/CoreData.cs b/src/UniGetUI.Core.Data/CoreData.cs index 5c17b6a055..1eac17c0db 100644 --- a/src/UniGetUI.Core.Data/CoreData.cs +++ b/src/UniGetUI.Core.Data/CoreData.cs @@ -1,7 +1,4 @@ using System.Diagnostics; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Text.Json.Serialization.Metadata; using UniGetUI.Core.Logging; namespace UniGetUI.Core.Data diff --git a/src/UniGetUI.Core.LanguageEngine/LanguageData.cs b/src/UniGetUI.Core.LanguageEngine/LanguageData.cs index 8c374f7e64..07e6d10cc6 100644 --- a/src/UniGetUI.Core.LanguageEngine/LanguageData.cs +++ b/src/UniGetUI.Core.LanguageEngine/LanguageData.cs @@ -1,11 +1,9 @@ using System.Collections.ObjectModel; -using System.Runtime.InteropServices; using System.Text.Json.Nodes; using UniGetUI.Core.Classes; using UniGetUI.Core.Data; using UniGetUI.Core.Logging; using UniGetUI.PackageEngine.Enums; -using Architecture = UniGetUI.PackageEngine.Enums.Architecture; namespace UniGetUI.Core.Language { diff --git a/src/UniGetUI.Core.SecureSettings/SecureSettings.cs b/src/UniGetUI.Core.SecureSettings/SecureSettings.cs index 11b2d0044e..7ffe30fbc7 100644 --- a/src/UniGetUI.Core.SecureSettings/SecureSettings.cs +++ b/src/UniGetUI.Core.SecureSettings/SecureSettings.cs @@ -1,8 +1,6 @@ using System.Diagnostics; using UniGetUI.Core.Data; using UniGetUI.Core.Tools; -using YamlDotNet.Core.Tokens; -using YamlDotNet.Serialization; namespace UniGetUI.Core.SettingsEngine.SecureSettings; diff --git a/src/UniGetUI.Core.Tools/SerializationHelpers.cs b/src/UniGetUI.Core.Tools/SerializationHelpers.cs index be129d130b..4172b94dc2 100644 --- a/src/UniGetUI.Core.Tools/SerializationHelpers.cs +++ b/src/UniGetUI.Core.Tools/SerializationHelpers.cs @@ -1,7 +1,6 @@ using System.Globalization; using System.Text.Json; using System.Text.Json.Nodes; -using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; using System.Xml; diff --git a/src/UniGetUI.PackageEngine.Enums/ManagerCapabilities.cs b/src/UniGetUI.PackageEngine.Enums/ManagerCapabilities.cs index e9f14bf2af..ad224ea79e 100644 --- a/src/UniGetUI.PackageEngine.Enums/ManagerCapabilities.cs +++ b/src/UniGetUI.PackageEngine.Enums/ManagerCapabilities.cs @@ -1,5 +1,3 @@ -using System.Runtime.InteropServices; - namespace UniGetUI.PackageEngine.ManagerClasses.Manager { public enum ProxySupport diff --git a/src/UniGetUI.PackageEngine.Enums/OverridenInstallationOptions.cs b/src/UniGetUI.PackageEngine.Enums/OverridenInstallationOptions.cs index 052363b0d0..75bdc7df31 100644 --- a/src/UniGetUI.PackageEngine.Enums/OverridenInstallationOptions.cs +++ b/src/UniGetUI.PackageEngine.Enums/OverridenInstallationOptions.cs @@ -1,5 +1,3 @@ -using UniGetUI.PackageEngine.Enums; - namespace UniGetUI.PackageEngine.Structs; public struct OverridenInstallationOptions { diff --git a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs index d76cbe26e8..0a3c486d9b 100644 --- a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs +++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs @@ -1,5 +1,4 @@ using System.Diagnostics; -using System.Runtime.InteropServices; using UniGetUI.Core.Data; using UniGetUI.Core.Logging; using UniGetUI.Core.SettingsEngine; diff --git a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateyPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateyPkgOperationHelper.cs index b9e5d70f3b..86b962f272 100644 --- a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateyPkgOperationHelper.cs +++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateyPkgOperationHelper.cs @@ -1,4 +1,3 @@ -using System.Runtime.InteropServices; using UniGetUI.PackageEngine.Classes.Manager.BaseProviders; using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; diff --git a/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs b/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs index e1476affdf..82225200c6 100644 --- a/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs +++ b/src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs @@ -1,5 +1,4 @@ using System.Diagnostics; -using System.Runtime.InteropServices; using System.Text.RegularExpressions; using UniGetUI.Core.Tools; using UniGetUI.Interface.Enums; diff --git a/src/UniGetUI.PackageEngine.Managers.Dotnet/Helpers/DotNetPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.Dotnet/Helpers/DotNetPkgOperationHelper.cs index 210ce71977..944e03f0b5 100644 --- a/src/UniGetUI.PackageEngine.Managers.Dotnet/Helpers/DotNetPkgOperationHelper.cs +++ b/src/UniGetUI.PackageEngine.Managers.Dotnet/Helpers/DotNetPkgOperationHelper.cs @@ -1,4 +1,3 @@ -using System.Runtime.InteropServices; using UniGetUI.PackageEngine.Classes.Manager.BaseProviders; using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; diff --git a/src/UniGetUI.PackageEngine.Managers.Scoop/Helpers/ScoopPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.Scoop/Helpers/ScoopPkgOperationHelper.cs index 58cb4214a9..0443aaaa6d 100644 --- a/src/UniGetUI.PackageEngine.Managers.Scoop/Helpers/ScoopPkgOperationHelper.cs +++ b/src/UniGetUI.PackageEngine.Managers.Scoop/Helpers/ScoopPkgOperationHelper.cs @@ -1,4 +1,3 @@ -using System.Runtime.InteropServices; using UniGetUI.PackageEngine.Classes.Manager.BaseProviders; using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; diff --git a/src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs b/src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs index 049ae08f65..65c4176cb4 100644 --- a/src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs +++ b/src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs @@ -1,5 +1,4 @@ using System.Diagnostics; -using System.Runtime.InteropServices; using System.Text.RegularExpressions; using UniGetUI.Core.Classes; using UniGetUI.Core.Logging; diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/NativePackageHandler.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/NativePackageHandler.cs index 5dc9607547..c3f8149d3a 100644 --- a/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/NativePackageHandler.cs +++ b/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/NativePackageHandler.cs @@ -1,10 +1,8 @@ using System.Collections.Concurrent; -using System.Linq.Expressions; using Microsoft.Management.Deployment; using UniGetUI.Core.Logging; using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; -using UniGetUI.PackageEngine.Serializable; using InstallOptions = UniGetUI.PackageEngine.Serializable.InstallOptions; namespace UniGetUI.PackageEngine.Managers.WingetManager; diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/WinGetIconsHelper.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/WinGetIconsHelper.cs index 7fee66356a..8523ac33c0 100644 --- a/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/WinGetIconsHelper.cs +++ b/src/UniGetUI.PackageEngine.Managers.WinGet/ClientHelpers/WinGetIconsHelper.cs @@ -1,7 +1,5 @@ using System.Globalization; using System.Net; -using System.Reflection; -using System.Text; using System.Text.RegularExpressions; using Microsoft.Management.Deployment; using Microsoft.Win32; diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/Helpers/WinGetPkgDetailsHelper.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/Helpers/WinGetPkgDetailsHelper.cs index 2ebf3b4d49..71ee33ab9d 100644 --- a/src/UniGetUI.PackageEngine.Managers.WinGet/Helpers/WinGetPkgDetailsHelper.cs +++ b/src/UniGetUI.PackageEngine.Managers.WinGet/Helpers/WinGetPkgDetailsHelper.cs @@ -1,8 +1,6 @@ -using System.ComponentModel.Design; using System.Text.RegularExpressions; using UniGetUI.Core.IconEngine; using UniGetUI.Core.Logging; -using UniGetUI.Core.Tools; using UniGetUI.PackageEngine.Classes.Manager.BaseProviders; using UniGetUI.PackageEngine.Interfaces; using UniGetUI.PackageEngine.Managers.WinGet.ClientHelpers; diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/Helpers/WinGetPkgOperationHelper.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/Helpers/WinGetPkgOperationHelper.cs index e1e8b0b47d..fbe0c818da 100644 --- a/src/UniGetUI.PackageEngine.Managers.WinGet/Helpers/WinGetPkgOperationHelper.cs +++ b/src/UniGetUI.PackageEngine.Managers.WinGet/Helpers/WinGetPkgOperationHelper.cs @@ -1,4 +1,3 @@ -using System.Runtime.InteropServices; using Microsoft.Management.Deployment; using UniGetUI.Core.Logging; using UniGetUI.Core.SettingsEngine; @@ -7,7 +6,6 @@ using UniGetUI.PackageEngine.Classes.Packages.Classes; using UniGetUI.PackageEngine.Enums; using UniGetUI.PackageEngine.Interfaces; -using UniGetUI.PackageEngine.Serializable; using Architecture = UniGetUI.PackageEngine.Enums.Architecture; using InstallOptions = UniGetUI.PackageEngine.Serializable.InstallOptions; diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs index 353f50b248..b9964b730c 100644 --- a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs +++ b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs @@ -1,6 +1,4 @@ -using System.ComponentModel; using System.Diagnostics; -using System.Runtime.InteropServices; using System.Security.AccessControl; using System.Security.Principal; using System.Text; diff --git a/src/UniGetUI.PackageEngine.Operations/AbstractOperation.cs b/src/UniGetUI.PackageEngine.Operations/AbstractOperation.cs index 9876844968..45366c932e 100644 --- a/src/UniGetUI.PackageEngine.Operations/AbstractOperation.cs +++ b/src/UniGetUI.PackageEngine.Operations/AbstractOperation.cs @@ -2,7 +2,6 @@ using UniGetUI.Core.SettingsEngine; using UniGetUI.Core.Tools; using UniGetUI.PackageEngine.Enums; -using YamlDotNet.Serialization.ObjectGraphVisitors; namespace UniGetUI.PackageOperations; diff --git a/src/UniGetUI/App.xaml.cs b/src/UniGetUI/App.xaml.cs index 347912e14f..6f3c632abe 100644 --- a/src/UniGetUI/App.xaml.cs +++ b/src/UniGetUI/App.xaml.cs @@ -15,7 +15,6 @@ using UniGetUI.PackageEngine.Classes.Manager.Classes; using Microsoft.Windows.AppLifecycle; using Microsoft.Windows.AppNotifications; -using UniGetUI.Core.SettingsEngine.SecureSettings; using UniGetUI.Interface.Telemetry; using UniGetUI.PackageEngine.Interfaces; using LaunchActivatedEventArgs = Microsoft.UI.Xaml.LaunchActivatedEventArgs; diff --git a/src/UniGetUI/CrashHandler.cs b/src/UniGetUI/CrashHandler.cs index 161ae8bfaf..9f25e0efe2 100644 --- a/src/UniGetUI/CrashHandler.cs +++ b/src/UniGetUI/CrashHandler.cs @@ -1,7 +1,5 @@ using System.Diagnostics; -using Microsoft.UI; using UniGetUI.Core.Data; -using UniGetUI.Core.Language; using UniGetUI.Core.Tools; namespace UniGetUI; diff --git a/src/UniGetUI/EntryPoint.cs b/src/UniGetUI/EntryPoint.cs index 20514ed893..37f88c4db8 100644 --- a/src/UniGetUI/EntryPoint.cs +++ b/src/UniGetUI/EntryPoint.cs @@ -3,7 +3,6 @@ using Microsoft.Windows.AppLifecycle; using UniGetUI.Core.Data; using UniGetUI.Core.Logging; -using UniGetUI.Core.Tools; namespace UniGetUI { diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml index de276ac5a8..d735d0d865 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml @@ -354,7 +354,6 @@ x:Name="KillProcessesBox" HorizontalAlignment="Left" ItemsSource="{x:Bind ProcessesToKill, Mode=TwoWay}" - Loaded="KillProcessesBox_Loaded" PlaceholderText="" SuggestedItemTemplate="{StaticResource ProcessTemplate}" SuggestedItemsSource="{x:Bind SuggestedProcesses, Mode=OneWay}" diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs index ddd9f9dfd4..5be1d7b93b 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs @@ -472,12 +472,7 @@ private async void KillProcessesBox_TextChanged(AutoSuggestBox sender, AutoSugge } } } - - private void KillProcessesBox_Loaded(object sender, RoutedEventArgs e) - { - - } - + private void SettingsTabBar_SelectionChanged(object sender, SelectionChangedEventArgs e) { CommandLineViewBox.Visibility = SettingsTabBar.SelectedIndex < 3 ? Visibility.Visible : Visibility.Collapsed; diff --git a/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs b/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs index 85d09a9407..cb68d9b129 100644 --- a/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs +++ b/src/UniGetUI/Pages/SoftwarePages/AbstractPackagesPage.xaml.cs @@ -1,7 +1,6 @@ using System.Collections.Concurrent; using System.Collections.ObjectModel; using System.Diagnostics; -using System.Runtime.Serialization; using Microsoft.UI.Input; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; From 791218c8c4b6ca5ccb382d7f1915696307f988ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Climent?= Date: Fri, 20 Jun 2025 12:36:07 +0200 Subject: [PATCH 12/12] Fix build --- .../PackageOperations.cs | 1 - src/UniGetUI/App.xaml.cs | 9 +++++---- .../Pages/DialogPages/InstallOptions_Manager.xaml.cs | 4 ---- .../Pages/DialogPages/InstallOptions_Package.xaml.cs | 8 +------- src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs | 2 -- 5 files changed, 6 insertions(+), 18 deletions(-) diff --git a/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs b/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs index 4970b69944..a133ff1619 100644 --- a/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs +++ b/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs @@ -1,4 +1,3 @@ -using System.Runtime.CompilerServices; using UniGetUI.Core.Classes; using UniGetUI.Core.Data; using UniGetUI.Core.SettingsEngine; diff --git a/src/UniGetUI/App.xaml.cs b/src/UniGetUI/App.xaml.cs index 6f3c632abe..2d2056ba5e 100644 --- a/src/UniGetUI/App.xaml.cs +++ b/src/UniGetUI/App.xaml.cs @@ -15,6 +15,7 @@ using UniGetUI.PackageEngine.Classes.Manager.Classes; using Microsoft.Windows.AppLifecycle; using Microsoft.Windows.AppNotifications; +using UniGetUI.Core.SettingsEngine.SecureSettings; using UniGetUI.Interface.Telemetry; using UniGetUI.PackageEngine.Interfaces; using LaunchActivatedEventArgs = Microsoft.UI.Xaml.LaunchActivatedEventArgs; @@ -94,10 +95,6 @@ public MainApp() private static async void LoadGSudo() { -#if DEBUG - Logger.Warn($"Using bundled GSudo at {CoreData.ElevatorPath} since UniGetUI Elevator is not available!"); - CoreData.ElevatorPath = (await CoreTools.WhichAsync("gsudo.exe")).Item2; -#else if (SecureSettings.Get(SecureSettings.K.ForceUserGSudo)) { var res = await CoreTools.WhichAsync("gsudo.exe"); @@ -109,6 +106,10 @@ private static async void LoadGSudo() } } +#if DEBUG + Logger.Warn($"Using bundled GSudo at {CoreData.ElevatorPath} since UniGetUI Elevator is not available!"); + CoreData.ElevatorPath = (await CoreTools.WhichAsync("gsudo.exe")).Item2; +#else CoreData.ElevatorPath = Path.Join(CoreData.UniGetUIExecutableDirectory, "Assets", "Utilities", "UniGetUI Elevator.exe"); Logger.Debug($"Using built-in UniGetUI Elevator at {CoreData.ElevatorPath}"); #endif diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Manager.xaml.cs b/src/UniGetUI/Pages/DialogPages/InstallOptions_Manager.xaml.cs index deeef6fd16..29c068ce43 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions_Manager.xaml.cs +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Manager.xaml.cs @@ -1,7 +1,3 @@ -using System.Diagnostics; -using System.Runtime.InteropServices; -using CommunityToolkit.WinUI.Controls; -using Microsoft.Extensions.Options; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using UniGetUI.Core.Language; diff --git a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs index 5be1d7b93b..ba3468cad3 100644 --- a/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs +++ b/src/UniGetUI/Pages/DialogPages/InstallOptions_Package.xaml.cs @@ -1,10 +1,6 @@ using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Data; using System.Diagnostics; -using System.Runtime.InteropServices; using CommunityToolkit.WinUI.Controls; -using Microsoft.Extensions.Options; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media.Imaging; @@ -17,8 +13,6 @@ using UniGetUI.PackageEngine.PackageClasses; using UniGetUI.PackageEngine.Serializable; using UniGetUI.Pages.SettingsPages.GeneralPages; -using Windows.ApplicationModel.Activation; -using Windows.Services.Maps; using Architecture = UniGetUI.PackageEngine.Enums.Architecture; // To learn more about WinUI, the WinUI project structure, @@ -472,7 +466,7 @@ private async void KillProcessesBox_TextChanged(AutoSuggestBox sender, AutoSugge } } } - + private void SettingsTabBar_SelectionChanged(object sender, SelectionChangedEventArgs e) { CommandLineViewBox.Visibility = SettingsTabBar.SelectedIndex < 3 ? Visibility.Visible : Visibility.Collapsed; diff --git a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs index 962408b591..d8d7411db9 100644 --- a/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs +++ b/src/UniGetUI/Pages/SoftwarePages/PackageBundlesPage.cs @@ -1,8 +1,6 @@ using System.Diagnostics; -using System.Runtime.Serialization.Formatters; using System.Text.Json; using System.Text.Json.Nodes; -using System.Xml; using System.Xml.Serialization; using ExternalLibraries.Pickers; using Microsoft.UI.Text;