CLI tool for running Playbooks
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

147 lines
4.8 KiB

using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using TrustedUninstaller.Shared.Exceptions;
using TrustedUninstaller.Shared.Tasks;
using YamlDotNet.Serialization;
namespace TrustedUninstaller.Shared.Actions
{
public class CmdAction : ITaskAction
{
[YamlMember(typeof(string), Alias = "command")]
public string Command { get; set; }
[YamlMember(typeof(string), Alias = "timeout")]
public int? Timeout { get; set; }
[YamlMember(typeof(string), Alias = "wait")]
public bool Wait { get; set; } = true;
[YamlMember(typeof(bool), Alias = "exeDir")]
public bool ExeDir { get; set; } = false;
[YamlMember(typeof(string), Alias = "weight")]
public int ProgressWeight { get; set; } = 1;
public int GetProgressWeight() => ProgressWeight;
private bool InProgress { get; set; }
public void ResetProgress() => InProgress = false;
private int? ExitCode { get; set; }
public string? StandardError { get; set; }
public string StandardOutput { get; set; }
public string ErrorString() => $"CmdAction failed to run command '{Command}'.";
public UninstallTaskStatus GetStatus()
{
if (InProgress)
{
return UninstallTaskStatus.InProgress;
}
return ExitCode == null ? UninstallTaskStatus.ToDo: UninstallTaskStatus.Completed;
}
public async Task<bool> RunTask()
{
if (InProgress) throw new TaskInProgressException("Another Cmd action was called while one was in progress.");
InProgress = true;
Console.WriteLine($"Running cmd command '{Command}'...");
ExitCode = null;
var process = new Process();
var startInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Normal,
FileName = "cmd.exe",
Arguments = "/C " + $"\"{Environment.ExpandEnvironmentVariables(this.Command)}\"",
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
CreateNoWindow = true
};
if (ExeDir) startInfo.WorkingDirectory = AmeliorationUtil.Playbook.Path + "\\Executables";
if (!Wait)
{
startInfo.RedirectStandardError = false;
startInfo.RedirectStandardOutput = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.UseShellExecute = true;
}
process.StartInfo = startInfo;
process.Start();
if (!Wait)
{
process.Dispose();
return true;
}
process.OutputDataReceived += ProcOutputHandler;
process.BeginOutputReadLine();
if (Timeout != null)
{
var exited = process.WaitForExit(Timeout.Value);
if (!exited)
{
process.Kill();
throw new TimeoutException($"Command '{Command}' timeout exceeded.");
}
}
else process.WaitForExit();
if (process.ExitCode != 0)
{
StandardError = process.StandardError.ReadToEnd();
Console.WriteLine($"cmd instance exited with error code: {process.ExitCode}");
if (!String.IsNullOrEmpty(StandardError)) Console.WriteLine($"Error message: {StandardError}");
ErrorLogger.WriteToErrorLog("Cmd exited with a non-zero exit code: " + process.ExitCode, null, "CmdAction Error", Command);
this.ExitCode = process.ExitCode;
}
else
{
ExitCode = 0;
}
process.CancelOutputRead();
process.Dispose();
InProgress = false;
return true;
}
private static void ProcOutputHandler(object sendingProcess,
DataReceivedEventArgs outLine)
{
var outputString = outLine.Data;
// Collect the sort command output.
if (!String.IsNullOrEmpty(outLine.Data))
{
if (outputString.Contains("\\AME"))
{
outputString = outputString.Substring(outputString.IndexOf('>') + 1);
}
Console.WriteLine(outputString);
}
else
{
Console.WriteLine();
}
}
}
}