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.

145 lines
4.9 KiB

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