环境:net framework 4.5.2


  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using TaskScheduler;
  7. namespace DrwmePMS.InstallService {
  8. public class LffTaskExt<T> where T : ITrigger {
  9. //初始化静态资源
  10. private static TaskSchedulerClass ts = new TaskSchedulerClass();
  11. /// <summary>
  12. /// 删除计划程序
  13. /// </summary>
  14. /// <param name="taskName"></param>
  15. private static void DeleteTask(string taskName) {
  16. //TaskSchedulerClass ts = new TaskSchedulerClass();
  17. ts.Connect(null, null, null, null);
  18. ts.GetFolder("\\Drwme").DeleteTask(taskName, 0);
  19. }
  20. /// <summary>
  21. /// 获取所有计划程序
  22. /// </summary>
  23. public static IRegisteredTaskCollection GetAllTasks() {
  24. //TaskSchedulerClass ts = new TaskSchedulerClass();
  25. ts.Connect(null, null, null, null);
  26. ITaskFolder folder = ts.GetFolder("\\");
  27. //如果您尝试创建的文件夹已存在,则 CreateFolder 方法将返回0x800700b7 。坑 半天才找到 所以这里应该直接用异常捕捉
  28. try { folder.CreateFolder("Drwme"); } catch (Exception) { }
  29. return ts.GetFolder("\\Drwme").GetTasks(1);
  30. }
  31. /// <summary>
  32. /// 判断计划程序是否存在
  33. /// </summary>
  34. /// <param name="taskName"></param>
  35. /// <returns></returns>
  36. public static bool IsExists(string taskName) {
  37. IRegisteredTaskCollection tasks_exists = GetAllTasks();
  38. foreach (var item in tasks_exists) if (item is IRegisteredTask t) if (t.Name.Equals(taskName)) return true;
  39. return false;
  40. }
  41. /// <summary>
  42. /// 创建计划程序 攻略文档 https://docs.microsoft.com/en-us/windows/win32/api/taskschd/nf-taskschd-iweeklytrigger-put_daysofweek
  43. /// </summary>
  44. /// <param name="type">指定计划程序的执行类型</param>
  45. /// <param name="creator">创建者</param>
  46. /// <param name="taskName">程序名称</param>
  47. /// <param name="path">执行文件需要提供文件路径</param>
  48. /// <param name="interval"></param>
  49. /// <param name="triggerTime"></param>
  50. /// <param name="description"></param>
  51. /// <param name="parameter"></param>
  52. public static void CreateTaskScheduler(_TASK_TRIGGER_TYPE2 type, string creator, string taskName, string path, string interval, string triggerTime, string description, params string[] parameter) {
  53. try {
  54. //存在则删除
  55. if (IsExists(taskName)) DeleteTask(taskName);
  56. //创建新任务计划程序
  57. //TaskSchedulerClass scheduler = new TaskSchedulerClass();
  58. //打开连接 pc-name/ip,username,domain,password 不写会报错
  59. ts.Connect(null, null, null, null);
  60. //设置程序为根目录 - 在GetAllTasks里面已经做好的文件夹创建 这里用到公司标识文件夹,防止服务器根目录太多计划程序找不到
  61. ITaskFolder folder = ts.GetFolder("\\Drwme");
  62. //此参数保留供将来使用,必须设置为 0。官方提供参数说明
  63. ITaskDefinition task = ts.NewTask(0);
  64. //创建者
  65. task.RegistrationInfo.Author = creator;
  66. //主体描述
  67. task.RegistrationInfo.Description = description;
  68. //mmp 这里有多个类型枚举类型,所以需要使用高级类型语法泛型约束接口防止二次开发瞎几把传递类型
  69. //泛型创建 类型太多不想使用if 和 switch来判断
  70. T tt = tt = (T)task.Triggers.Create(type);
  71. //位掩码运算
  72. //月 十六进制值 十进制值
  73. //星期日 0X01 1
  74. //周一 0x02 2
  75. //周二 0X04 4
  76. //周三 0X08 8
  77. //周四 0X10 16
  78. //星期五 0x20 32
  79. //周六 0X40 64
  80. //一周可以指定哪几天触发 这里就按照十进制加算 比如周日1 + 周二4 = 5
  81. if (tt is IWeeklyTrigger a) a.DaysOfWeek = 1;
  82. // PT1H1M==1小时1分钟 设置的值最终都会转成分钟加入到触发器
  83. tt.Repetition.Interval = interval;
  84. //触发器的第一次开始时间
  85. tt.StartBoundary = triggerTime;
  86. //设置主体
  87. IExecAction action = (IExecAction)task.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC);
  88. //执行路径
  89. action.Path = path;
  90. //执行程序的参数
  91. action.Arguments = string.Join(" ", parameter);
  92. //运行任务时间超时停止任务吗? PTOS 不开启超时
  93. task.Settings.ExecutionTimeLimit = "PT0S";
  94. //只有在交流电源下才执行
  95. task.Settings.DisallowStartIfOnBatteries = false;
  96. //仅当计算机空闲下才执行
  97. task.Settings.RunOnlyIfIdle = false;
  98. //user null, password null
  99. IRegisteredTask regTask = folder.RegisterTaskDefinition(taskName, task, (int)_TASK_CREATION.TASK_CREATE, null, null, _TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN, "");
  100. //立即运行
  101. //IRunningTask runTask = regTask.Run(null);
  102. //return runTask.State;
  103. } catch (Exception ex) {
  104. throw ex;
  105. }
  106. }
  107. }
  108. }
  1. class Program {
  2. static void Main(string[] args) {
  3. var currentDate = DateTime.Now;
  4. Console.WriteLine("-----PMS计划程序开始注入中-----");
  5. //执行的程序路径
  6. //var path = GetFilePath("DrwmePMS.Service", "DrwmePMS.Service.exe");//开发环境
  7. var path = GetFilePath("Service", "DrwmePMS.Service.exe");//生产环境
  8. //每天计划程序
  9. LffTaskExt<IDailyTrigger>.CreateTaskScheduler(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_DAILY, "LFF", "PMS自动化发送邮件服务Day20", path,
  10. "PT20H0M", (DateTime.Now.ToString("yyyy-MM-dd") + "T20:00:00"), "DrwmePMS.Service自调用初始化服务", new string[] { "-Report", "-Day" });
  11. //每周计划程序
  12. LffTaskExt<IWeeklyTrigger>.CreateTaskScheduler(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_WEEKLY, "LFF", "PMS自动化发送邮件服务Week20", path,
  13. "PT20H0M", (DateTime.Now.ToString("yyyy-MM-dd") + "T20:00:00"), "DrwmePMS.Service自调用初始化服务", new string[] { "-Report", "-Week" });
  14. Console.WriteLine("-----PMS计划程序注入成功-----");
  15. Thread.Sleep(3000);
  16. }
  17. }

效果图taskschd.key(当前文件需要变更为zip或者rar,因为这是个压缩包)这是当前功能所使用得系统dll

常见问题

  1. 无法嵌入互操作类型

详见图片

变更为Flase