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.

136 lines
4.5 KiB

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