using System; using System.ComponentModel; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; namespace Artemis.Core { /// /// Represents a plugin prerequisite action that executes a file /// public class ExecuteFileAction : PluginPrerequisiteAction { /// /// Creates a new instance of /// /// The name of the action /// 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 public ExecuteFileAction(string name, string fileName, string? arguments = null, bool waitForExit = true, bool elevate = false) : base(name) { FileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); Arguments = arguments; WaitForExit = waitForExit; Elevate = elevate; } /// /// Gets the target file to execute /// public string FileName { get; } /// /// Gets a set of command-line arguments to use when starting the application /// public string? Arguments { get; } /// /// Gets a boolean indicating whether the action should wait for the process to exit /// public bool WaitForExit { 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 (WaitForExit) { Status = $"Running {FileName} and waiting for exit.."; ShowProgressBar = true; ProgressIndeterminate = true; int result = await RunProcessAsync(FileName, Arguments, Elevate); Status = $"{FileName} exited with code {result}"; } else { Status = $"Running {FileName}"; Process process = new() { StartInfo = {FileName = FileName, Arguments = Arguments!}, EnableRaisingEvents = true }; process.Start(); } } internal static Task RunProcessAsync(string fileName, string? arguments, bool elevate) { TaskCompletionSource tcs = new(); Process process = new() { StartInfo = { FileName = fileName, Arguments = arguments!, Verb = elevate ? "RunAs" : "", UseShellExecute = elevate }, EnableRaisingEvents = true }; process.Exited += (_, _) => { tcs.SetResult(process.ExitCode); process.Dispose(); }; try { process.Start(); } catch (Win32Exception e) { if (!elevate || e.NativeErrorCode != 0x4c7) throw; tcs.SetResult(-1); } return tcs.Task; } } }