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.

151 lines
5.2 KiB

1 year ago
10 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 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. // Integrate ame-assassin later
  14. internal class SystemPackageAction : TaskAction, ITaskAction
  15. {
  16. public void RunTaskOnMainThread() { throw new NotImplementedException(); }
  17. public enum Architecture
  18. {
  19. amd64 = 0,
  20. wow64 = 1,
  21. msil = 2,
  22. x86 = 3,
  23. All = 4
  24. }
  25. [YamlMember(typeof(string), Alias = "name")]
  26. public string Name { get; set; }
  27. [YamlMember(typeof(string), Alias = "arch")]
  28. public Architecture Arch { get; set; } = Architecture.All;
  29. [YamlMember(typeof(string), Alias = "language")]
  30. public string Language { get; set; } = "*";
  31. [YamlMember(typeof(string), Alias = "regexExcludeFiles")]
  32. public string[]? RegexExcludeList { get; set; }
  33. [YamlMember(typeof(string), Alias = "excludeDependents")]
  34. public string[]? ExcludeDependentsList { get; set; }
  35. [YamlMember(typeof(string[]), Alias = "weight")]
  36. public int ProgressWeight { get; set; } = 15;
  37. public int GetProgressWeight() => ProgressWeight;
  38. private bool InProgress { get; set; }
  39. public void ResetProgress() => InProgress = false;
  40. public string ErrorString() => $"SystemPackageAction failed to remove '{Name}'.";
  41. public UninstallTaskStatus GetStatus()
  42. {
  43. if (InProgress) return UninstallTaskStatus.InProgress;
  44. return HasFinished ? UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo;
  45. }
  46. private bool HasFinished = false;
  47. public async Task<bool> RunTask()
  48. {
  49. if (InProgress) throw new TaskInProgressException("Another Appx action was called while one was in progress.");
  50. InProgress = true;
  51. Console.WriteLine($"Removing system package '{Name}'...");
  52. var excludeArgs = new StringBuilder("");
  53. if (RegexExcludeList != null)
  54. {
  55. foreach (var regex in RegexExcludeList)
  56. {
  57. excludeArgs.Append(@$" -xf ""{regex}""");
  58. }
  59. }
  60. var excludeDependsArgs = new StringBuilder("");
  61. if (ExcludeDependentsList != null)
  62. {
  63. foreach (var dependent in ExcludeDependentsList)
  64. {
  65. excludeDependsArgs.Append(@$" -xdependent ""{dependent}""");
  66. }
  67. }
  68. string kernelDriverArg = AmeliorationUtil.UseKernelDriver ? " -UseKernelDriver" : "";
  69. var psi = new ProcessStartInfo()
  70. {
  71. UseShellExecute = false,
  72. CreateNoWindow = true,
  73. Arguments = $@"-SystemPackage ""{Name}"" -Arch {Arch.ToString()} -Language ""{Language}""" + excludeArgs + excludeDependsArgs + kernelDriverArg,
  74. FileName = Directory.GetCurrentDirectory() + "\\ame-assassin\\ame-assassin.exe",
  75. RedirectStandardOutput = true,
  76. RedirectStandardError = true
  77. };
  78. var proc = Process.Start(psi);
  79. proc.OutputDataReceived += ProcOutputHandler;
  80. proc.ErrorDataReceived += ProcOutputHandler;
  81. proc.BeginOutputReadLine();
  82. proc.BeginErrorReadLine();
  83. bool exited = proc.WaitForExit(30000);
  84. // WaitForExit alone seems to not be entirely reliable
  85. while (!exited && ExeRunning(proc))
  86. {
  87. exited = proc.WaitForExit(30000);
  88. }
  89. using (var log = new StreamWriter("Logs\\Packages.txt", true))
  90. log.Write(output.ToString());
  91. HasFinished = true;
  92. InProgress = false;
  93. return true;
  94. }
  95. private StringBuilder output = new StringBuilder("");
  96. private bool PleaseWait = false;
  97. private void ProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
  98. {
  99. var write = outLine == null ? "" : outLine.Data;
  100. output.Append(write + Environment.NewLine);
  101. if (String.IsNullOrEmpty(write)) return;
  102. if (write.StartsWith("--- Removing"))
  103. {
  104. Console.WriteLine(write.Substring(4, write.Length - 4));
  105. PleaseWait = true;
  106. }
  107. if (write.StartsWith("Waiting for the service to stop...") && PleaseWait)
  108. {
  109. PleaseWait = false;
  110. Console.WriteLine("This may take some time...");
  111. }
  112. }
  113. private static bool ExeRunning(Process process)
  114. {
  115. try
  116. {
  117. return Process.GetProcessesByName(process.ProcessName).Any(x => x.Id == process.Id);
  118. }
  119. catch (Exception)
  120. {
  121. return false;
  122. }
  123. }
  124. }
  125. }