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