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.

163 lines
5.4 KiB

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