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.

133 lines
4.4 KiB

1 year ago
1 year ago
1 year ago
  1. using System;
  2. using System.Linq;
  3. using System.Threading.Tasks;
  4. using TrustedUninstaller.Shared.Exceptions;
  5. using TrustedUninstaller.Shared.Tasks;
  6. using YamlDotNet.Serialization;
  7. using System.Diagnostics;
  8. using System.IO;
  9. using System.Text;
  10. using System.Threading;
  11. namespace TrustedUninstaller.Shared.Actions
  12. {
  13. internal class AppxAction : ITaskAction
  14. {
  15. public enum AppxOperation
  16. {
  17. Remove = 0,
  18. ClearCache = 1,
  19. }
  20. public enum Level
  21. {
  22. Family = 0,
  23. Package = 1,
  24. App = 2
  25. }
  26. [YamlMember(typeof(string), Alias = "name")]
  27. public string Name { get; set; }
  28. [YamlMember(typeof(Level), Alias = "type")]
  29. public Level? Type { get; set; } = Level.Family;
  30. [YamlMember(typeof(AppxOperation), Alias = "operation")]
  31. public AppxOperation Operation { get; set; } = AppxOperation.Remove;
  32. [YamlMember(typeof(bool), Alias = "verboseOutput")]
  33. public bool Verbose { get; set; } = false;
  34. [YamlMember(typeof(string), Alias = "weight")]
  35. public int ProgressWeight { get; set; } = 30;
  36. public int GetProgressWeight() => ProgressWeight;
  37. private bool InProgress { get; set; }
  38. public void ResetProgress() => InProgress = false;
  39. public string ErrorString() => $"AppxAction failed to remove '{Name}'.";
  40. /*
  41. private Package GetPackage()
  42. {
  43. var packageManager = new PackageManager();
  44. return packageManager.FindPackages().FirstOrDefault(package => package.Id.Name == Name);
  45. }
  46. */
  47. public UninstallTaskStatus GetStatus()
  48. {
  49. if (InProgress) return UninstallTaskStatus.InProgress;
  50. return HasFinished ? UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo;
  51. //return GetPackage() == null ? UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo;
  52. }
  53. private bool HasFinished = false;
  54. public async Task<bool> RunTask()
  55. {
  56. if (InProgress) throw new TaskInProgressException("Another Appx action was called while one was in progress.");
  57. InProgress = true;
  58. Console.WriteLine($"Removing APPX {Type.ToString().ToLower()} '{Name}'...");
  59. string verboseArg = Verbose ? " -Verbose" : "";
  60. var psi = new ProcessStartInfo()
  61. {
  62. UseShellExecute = false,
  63. CreateNoWindow = true,
  64. Arguments = $@"-{Type.ToString()} ""{Name}""" + verboseArg,
  65. FileName = Directory.GetCurrentDirectory() + "\\ame-assassin\\ame-assassin.exe",
  66. RedirectStandardOutput = true,
  67. RedirectStandardError = true
  68. };
  69. if (Operation == AppxOperation.ClearCache)
  70. {
  71. psi.Arguments = $@"-ClearCache ""{Name}""";
  72. }
  73. var proc = Process.Start(psi);
  74. proc.OutputDataReceived += ProcOutputHandler;
  75. proc.ErrorDataReceived += ProcOutputHandler;
  76. proc.BeginOutputReadLine();
  77. proc.BeginErrorReadLine();
  78. bool exited = proc.WaitForExit(30000);
  79. // WaitForExit alone seems to not be entirely reliable
  80. while (!exited && ExeRunning(proc))
  81. {
  82. exited = proc.WaitForExit(30000);
  83. }
  84. using (var log = new StreamWriter("Logs\\Packages.txt", true))
  85. log.Write(output.ToString());
  86. HasFinished = true;
  87. InProgress = false;
  88. return true;
  89. }
  90. private StringBuilder output = new StringBuilder("");
  91. private void ProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
  92. {
  93. var write = outLine.Data == null ? "" : outLine.Data;
  94. output.Append(write + Environment.NewLine);
  95. if (!write.Equals("Complete!")) Console.WriteLine(write);
  96. }
  97. private static bool ExeRunning(Process process)
  98. {
  99. try
  100. {
  101. return Process.GetProcessesByName(process.ProcessName).Any(x => x.Id == process.Id);
  102. }
  103. catch (Exception)
  104. {
  105. return false;
  106. }
  107. }
  108. }
  109. }