diff --git a/src/Artemis.Core/Plugins/Prerequisites/PluginPrerequisite.cs b/src/Artemis.Core/Plugins/Prerequisites/PluginPrerequisite.cs index 57c4850a7..3adc6fac1 100644 --- a/src/Artemis.Core/Plugins/Prerequisites/PluginPrerequisite.cs +++ b/src/Artemis.Core/Plugins/Prerequisites/PluginPrerequisite.cs @@ -22,11 +22,6 @@ namespace Artemis.Core /// public abstract string Description { get; } - /// - /// [NYI] Gets a boolean indicating whether installing or uninstalling this prerequisite requires admin privileges - /// - public abstract bool RequiresElevation { get; } - /// /// Gets a list of actions to execute when is called /// diff --git a/src/Artemis.Core/Plugins/Prerequisites/PrerequisiteAction/ExecuteFileAction.cs b/src/Artemis.Core/Plugins/Prerequisites/PrerequisiteAction/ExecuteFileAction.cs index fcfc4db19..e98f0f354 100644 --- a/src/Artemis.Core/Plugins/Prerequisites/PrerequisiteAction/ExecuteFileAction.cs +++ b/src/Artemis.Core/Plugins/Prerequisites/PrerequisiteAction/ExecuteFileAction.cs @@ -18,7 +18,7 @@ namespace Artemis.Core /// The target file to execute /// A set of command-line arguments to use when starting the application /// A boolean indicating whether the action should wait for the process to exit - /// A boolean indicating whether the file should run with administrator privileges (does not require ) + /// A boolean indicating whether the file should run with administrator privileges public ExecuteFileAction(string name, string fileName, string? arguments = null, bool waitForExit = true, bool elevate = false) : base(name) { FileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); @@ -72,7 +72,7 @@ namespace Artemis.Core } } - private static Task RunProcessAsync(string fileName, string? arguments, bool elevate) + internal static Task RunProcessAsync(string fileName, string? arguments, bool elevate) { TaskCompletionSource tcs = new(); diff --git a/src/Artemis.Core/Plugins/Prerequisites/PrerequisiteAction/RunInlinePowerShellAction.cs b/src/Artemis.Core/Plugins/Prerequisites/PrerequisiteAction/RunInlinePowerShellAction.cs new file mode 100644 index 000000000..08f6e63ca --- /dev/null +++ b/src/Artemis.Core/Plugins/Prerequisites/PrerequisiteAction/RunInlinePowerShellAction.cs @@ -0,0 +1,70 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Artemis.Core +{ + /// + /// Represents a plugin prerequisite action runs inline powershell + /// + public class RunInlinePowerShellAction : PluginPrerequisiteAction + { + /// + /// Creates a new instance of a copy folder action + /// + /// The name of the action + /// The inline code to run + /// A boolean indicating whether the file should run with administrator privileges + public RunInlinePowerShellAction(string name, string code, bool elevate = false) : base(name) + { + Code = code; + Elevate = elevate; + ProgressIndeterminate = true; + } + + /// + /// Gets the inline code to run + /// + public string Code { get; } + + /// + /// Gets a boolean indicating whether the file should run with administrator privileges + /// + public bool Elevate { get; } + + /// + public override async Task Execute(CancellationToken cancellationToken) + { + string file = Path.GetTempFileName().Replace(".tmp", ".ps1"); + try + { + string code = + @"try + { + " + Code + @" + Start-Sleep 1 + } + catch + { + Write-Error $_.Exception.ToString() + pause + }"; + + await File.WriteAllTextAsync(file, code, cancellationToken); + cancellationToken.ThrowIfCancellationRequested(); + + Status = "Running PowerShell script and waiting for exit.."; + ShowProgressBar = true; + ProgressIndeterminate = true; + + int result = await ExecuteFileAction.RunProcessAsync("powershell.exe", $"-File {file}", Elevate); + + Status = $"PowerShell exited with code {result}"; + } + finally + { + File.Delete(file); + } + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/Prerequisites/PrerequisiteAction/RunPowerShellAction.cs b/src/Artemis.Core/Plugins/Prerequisites/PrerequisiteAction/RunPowerShellAction.cs new file mode 100644 index 000000000..8255328ee --- /dev/null +++ b/src/Artemis.Core/Plugins/Prerequisites/PrerequisiteAction/RunPowerShellAction.cs @@ -0,0 +1,53 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Artemis.Core +{ + /// + /// Represents a plugin prerequisite action that runs a PowerShell script + /// Note: To run an inline script instead, use + /// + public class RunPowerShellAction : PluginPrerequisiteAction + { + /// + /// Creates a new instance of a copy folder action + /// + /// The name of the action + /// The full path of the script to run + /// A boolean indicating whether the file should run with administrator privileges + public RunPowerShellAction(string name, string scriptPath, bool elevate = false) : base(name) + { + ScriptPath = scriptPath; + Elevate = elevate; + ProgressIndeterminate = true; + } + + /// + /// Gets the inline full path of the script to run + /// + public string ScriptPath { get; } + + /// + /// Gets a boolean indicating whether the file should run with administrator privileges + /// + public bool Elevate { get; } + + /// + public override async Task Execute(CancellationToken cancellationToken) + { + if (!ScriptPath.EndsWith(".ps1")) + throw new ArtemisPluginException($"Script at path {ScriptPath} must have the .ps1 extension or PowerShell will refuse to run it"); + if (!File.Exists(ScriptPath)) + throw new ArtemisCoreException($"Script not found at path {ScriptPath}"); + + Status = "Running PowerShell script and waiting for exit.."; + ShowProgressBar = true; + ProgressIndeterminate = true; + + int result = await ExecuteFileAction.RunProcessAsync("powershell.exe", $"-File {ScriptPath}", Elevate); + + Status = $"PowerShell exited with code {result}"; + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Plugins/PluginPrerequisiteViewModel.cs b/src/Artemis.UI/Screens/Plugins/PluginPrerequisiteViewModel.cs index 841f79385..453ec9bac 100644 --- a/src/Artemis.UI/Screens/Plugins/PluginPrerequisiteViewModel.cs +++ b/src/Artemis.UI/Screens/Plugins/PluginPrerequisiteViewModel.cs @@ -13,18 +13,13 @@ namespace Artemis.UI.Screens.Plugins public class PluginPrerequisiteViewModel : Conductor.Collection.OneActive { private readonly bool _uninstall; - private readonly ICoreService _coreService; - private readonly IDialogService _dialogService; private bool _installing; private bool _uninstalling; private bool _isMet; - public PluginPrerequisiteViewModel(PluginPrerequisite pluginPrerequisite, bool uninstall, ICoreService coreService, IDialogService dialogService) + public PluginPrerequisiteViewModel(PluginPrerequisite pluginPrerequisite, bool uninstall) { _uninstall = uninstall; - _coreService = coreService; - _dialogService = dialogService; - PluginPrerequisite = pluginPrerequisite; } @@ -65,12 +60,6 @@ namespace Artemis.UI.Screens.Plugins if (Busy) return; - if (PluginPrerequisite.RequiresElevation && !_coreService.IsElevated) - { - await _dialogService.ShowConfirmDialog("Install plugin prerequisite", "This plugin prerequisite admin rights to install (restart & elevate NYI)"); - return; - } - Installing = true; try { @@ -88,12 +77,6 @@ namespace Artemis.UI.Screens.Plugins if (Busy) return; - if (PluginPrerequisite.RequiresElevation && !_coreService.IsElevated) - { - await _dialogService.ShowConfirmDialog("Install plugin prerequisite", "This plugin prerequisite admin rights to install (restart & elevate NYI)"); - return; - } - Uninstalling = true; try {