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.

153 lines
5.0 KiB

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. return folder == null ? UninstallTaskStatus.Completed : UninstallTaskStatus.ToDo;
  61. }
  62. }
  63. public async Task<bool> RunTask()
  64. {
  65. if (GetStatus() == UninstallTaskStatus.Completed)
  66. {
  67. return true;
  68. }
  69. if (InProgress) throw new TaskInProgressException("Another ScheduledTask action was called while one was in progress.");
  70. Console.WriteLine($"{Operation.ToString().TrimEnd('e')}ing scheduled task '{Path}'...");
  71. using TaskService ts = new TaskService();
  72. InProgress = true;
  73. if (Operation != ScheduledTaskOperation.DeleteFolder)
  74. {
  75. var task = ts.GetTask(Path);
  76. if (task is null)
  77. {
  78. if (Operation == ScheduledTaskOperation.Delete)
  79. {
  80. return true;
  81. }
  82. if (RawTask is null || RawTask.Length == 0)
  83. {
  84. return false;
  85. }
  86. }
  87. switch (Operation)
  88. {
  89. case ScheduledTaskOperation.Delete:
  90. // TODO: This will probably not work if we actually use sub-folders
  91. ts.RootFolder.DeleteTask(Path);
  92. break;
  93. case ScheduledTaskOperation.Enable:
  94. case ScheduledTaskOperation.Disable:
  95. {
  96. if (task is null && !(RawTask is null))
  97. {
  98. task = ts.RootFolder.RegisterTask(Path, RawTask);
  99. }
  100. if (!(task is null))
  101. {
  102. task.Enabled = Operation == ScheduledTaskOperation.Enable;
  103. }
  104. else
  105. {
  106. throw new ArgumentException($"Task provided is null.");
  107. }
  108. break;
  109. }
  110. default:
  111. throw new ArgumentException($"Argument out of range.");
  112. }
  113. InProgress = false;
  114. return true;
  115. }
  116. else
  117. {
  118. var folder = ts.GetFolder(Path);
  119. if (folder is null) return true;
  120. folder.GetTasks().ToList().ForEach(x => folder.DeleteTask(x.Name));
  121. folder.Parent.DeleteFolder(folder.Name);
  122. InProgress = false;
  123. return true;
  124. }
  125. }
  126. }
  127. }