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.

164 lines
5.5 KiB

1 year ago
10 months ago
1 year ago
6 months ago
1 year ago
1 year ago
1 year ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.DirectoryServices.ActiveDirectory;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using Microsoft.Win32.TaskScheduler;
  8. using TrustedUninstaller.Shared.Exceptions;
  9. using TrustedUninstaller.Shared.Tasks;
  10. using YamlDotNet.Serialization;
  11. namespace TrustedUninstaller.Shared.Actions
  12. {
  13. internal enum ScheduledTaskOperation
  14. {
  15. Delete = 0,
  16. Enable = 1,
  17. Disable = 2,
  18. DeleteFolder = 3
  19. }
  20. internal class ScheduledTaskAction : TaskAction, ITaskAction
  21. {
  22. public void RunTaskOnMainThread() { throw new NotImplementedException(); }
  23. [YamlMember(typeof(ScheduledTaskOperation), Alias = "operation")]
  24. public ScheduledTaskOperation Operation { get; set; } = ScheduledTaskOperation.Delete;
  25. [YamlMember(Alias = "data")]
  26. public string? RawTask { get; set; } = null;
  27. [YamlMember(Alias = "path")]
  28. public string Path { get; set; }
  29. [YamlMember(typeof(string), Alias = "weight")]
  30. public int ProgressWeight { get; set; } = 1;
  31. public int GetProgressWeight() => ProgressWeight;
  32. private bool InProgress { get; set; } = false;
  33. public void ResetProgress() => InProgress = false;
  34. public string ErrorString() => $"ScheduledTaskAction failed to change task {Path} to state {Operation.ToString()}";
  35. public UninstallTaskStatus GetStatus()
  36. {
  37. if (InProgress)
  38. {
  39. return UninstallTaskStatus.InProgress;
  40. }
  41. using TaskService ts = new TaskService();
  42. if (Operation != ScheduledTaskOperation.DeleteFolder)
  43. {
  44. var task = ts.GetTask(Path);
  45. if (task is null)
  46. {
  47. return Operation == ScheduledTaskOperation.Delete ?
  48. UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo;
  49. }
  50. if (task.Enabled)
  51. {
  52. return Operation == ScheduledTaskOperation.Enable ?
  53. UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo;
  54. }
  55. return Operation == ScheduledTaskOperation.Disable ?
  56. UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo;
  57. }
  58. else
  59. {
  60. var folder = ts.GetFolder(Path);
  61. if (folder == null)
  62. return UninstallTaskStatus.Completed;
  63. return folder.GetTasks().Any() ? UninstallTaskStatus.ToDo : UninstallTaskStatus.Completed;
  64. }
  65. }
  66. public async Task<bool> RunTask()
  67. {
  68. if (GetStatus() == UninstallTaskStatus.Completed)
  69. {
  70. return true;
  71. }
  72. if (InProgress) throw new TaskInProgressException("Another ScheduledTask action was called while one was in progress.");
  73. Console.WriteLine($"{Operation.ToString().TrimEnd('e')}ing scheduled task '{Path}'...");
  74. using TaskService ts = new TaskService();
  75. InProgress = true;
  76. if (Operation != ScheduledTaskOperation.DeleteFolder)
  77. {
  78. var task = ts.GetTask(Path);
  79. if (task is null)
  80. {
  81. if (Operation == ScheduledTaskOperation.Delete)
  82. {
  83. return true;
  84. }
  85. if (RawTask is null || RawTask.Length == 0)
  86. {
  87. return false;
  88. }
  89. }
  90. switch (Operation)
  91. {
  92. case ScheduledTaskOperation.Delete:
  93. // TODO: This will probably not work if we actually use sub-folders
  94. ts.RootFolder.DeleteTask(Path);
  95. break;
  96. case ScheduledTaskOperation.Enable:
  97. case ScheduledTaskOperation.Disable:
  98. {
  99. if (task is null && !(RawTask is null))
  100. {
  101. task = ts.RootFolder.RegisterTask(Path, RawTask);
  102. }
  103. if (!(task is null))
  104. {
  105. task.Enabled = Operation == ScheduledTaskOperation.Enable;
  106. }
  107. else
  108. {
  109. throw new ArgumentException($"Task provided is null.");
  110. }
  111. break;
  112. }
  113. default:
  114. throw new ArgumentException($"Argument out of range.");
  115. }
  116. InProgress = false;
  117. return true;
  118. }
  119. else
  120. {
  121. var folder = ts.GetFolder(Path);
  122. if (folder is null) return true;
  123. folder.GetTasks().ToList().ForEach(x => folder.DeleteTask(x.Name));
  124. try
  125. {
  126. folder.Parent.DeleteFolder(folder.Name);
  127. }
  128. catch (Exception e)
  129. {
  130. ErrorLogger.WriteToErrorLog(e.Message, e.StackTrace, "Error removing task folder.", folder.Name);
  131. }
  132. InProgress = false;
  133. return true;
  134. }
  135. }
  136. }
  137. }