zoukankan      html  css  js  c++  java
  • 使用C#创建计划任务(How to create a Task Scheduler use C# )

    本文主要讲解了如何使用C#来创建windows计划任务。

    •  需求:在不定时间段运行多个后台程序(winfrom,wpf,console,等等)用于更新数据。
    •  问题:为什么要使用计划任务,而不直接在程序中使用一个计时器来触发呢?

      •  答:最明显的一点,使用计时器程序一直在后台运行着,但需求中只需要一天运行一次,或一个月运行一次。一直后台跑着计时这不白浪费CPU资源么。
    •  解决方案:
      • 使用windows自带的计划任务 在控制面板中可以看到,手动新建计划任务。
      • 使用微软自带的类库TaskScheduler("c:windowssystem32 askchd.dll")来创建
      • 使用Process.Star() dos命令来创建计划任务
        • dos命令运行scheduler.exe 最简单实例:

          schtasks /create /sc minute /mo 1 /tn MyTask /tr calc.exe /st 09:00  //从9点开始每隔一分钟运行一次记事本

          具体帮助文档可在cmd命令框输入:

          >schtasks /?  

          >schtasks /create /?  

          >schtasks /delete /?

          >schtasks /query /?

          >schtasks /change /?

        • 还可参照:https://msdn.microsoft.com/en-us/library/windows/desktop/bb736357%28v=vs.85%29.aspx

    解决方案开始:

    這里选用微软自带的类库TaskScheduler,下面是封装过的代码,包含了删除计划任务、判断计划任务是否存在、获取所有的计划任务、创建计划任务 。(具体看详细注释):

    获取计划任务的列表:

         /// <summary>
            /// get all tasks
            /// </summary>
            public static IRegisteredTaskCollection GetAllTasks()
            {
                TaskSchedulerClass ts = new TaskSchedulerClass();
                ts.Connect(null, null, null, null);
                ITaskFolder folder = ts.GetFolder("\");
                IRegisteredTaskCollection tasks_exists = folder.GetTasks(1);
                return tasks_exists;
            } 
    View Code

    判断计划任务是否存在:

    /// <summary>
            /// check task isexists
            /// </summary>
            /// <param name="taskName"></param>
            /// <returns></returns>
             public static bool IsExists(string taskName)
            {
                var isExists = false;
                IRegisteredTaskCollection tasks_exists = GetAllTasks();
                for (int i = 1; i <= tasks_exists.Count; i++)
                {
                    IRegisteredTask t = tasks_exists[i];
                    if (t.Name.Equals(taskName))
                    {
                        isExists=true;
                        break;
                    }
                }
                return isExists;
            }
    View Code

    删除计划任务:

     /// <summary>
            /// delete task
            /// </summary>
            /// <param name="taskName"></param>
            private static void DeleteTask(string taskName)
            {
                TaskSchedulerClass ts = new TaskSchedulerClass();
                ts.Connect(null, null, null, null);
                ITaskFolder folder = ts.GetFolder("\");
                folder.DeleteTask(taskName, 0);
            }
    View Code

    创建计划任务:

     /// <summary>
            /// create scheduler
            /// </summary>
            /// <param name="creator"></param>
            /// <param name="taskName"></param>
            /// <param name="path"></param>
            /// <param name="interval"></param>
            /// <param name="startBoundary"></param>
            /// <param name="description"></param>
            /// <returns></returns>
             public static _TASK_STATE CreateTaskScheduler(string creator, string taskName, string path,string interval,string startBoundary,string description)
            {
                try
                {
                    if (IsExists(taskName))
                    {
                        DeleteTask(taskName);
                    }
    
                    //new scheduler
                    TaskSchedulerClass scheduler = new TaskSchedulerClass();
                    //pc-name/ip,username,domain,password
                    scheduler.Connect(null, null, null, null); 
                    //get scheduler folder
                    ITaskFolder folder = scheduler.GetFolder("\");
                    
    
                    //set base attr 
                    ITaskDefinition task = scheduler.NewTask(0);
                    task.RegistrationInfo.Author = creator;//creator
                    task.RegistrationInfo.Description = description;//description
    
                    //set trigger  (IDailyTrigger ITimeTrigger)
                    ITimeTrigger tt = (ITimeTrigger)task.Triggers.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_TIME);
                    tt.Repetition.Interval = interval;// format PT1H1M==1小时1分钟 设置的值最终都会转成分钟加入到触发器
                    tt.StartBoundary = startBoundary;//start time
    
                    //set action
                    IExecAction action = (IExecAction)task.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC);
                    action.Path = path;//计划任务调用的程序路径
    
                    task.Settings.ExecutionTimeLimit = "PT0S"; //运行任务时间超时停止任务吗? PTOS 不开启超时
                    task.Settings.DisallowStartIfOnBatteries = false;//只有在交流电源下才执行
                    task.Settings.RunOnlyIfIdle = false;//仅当计算机空闲下才执行
    
                    IRegisteredTask regTask = folder.RegisterTaskDefinition(taskName, task,
                                                                        (int)_TASK_CREATION.TASK_CREATE, null, //user
                                                                        null, // password
                                                                        _TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN,
                                                                        "");
                    IRunningTask runTask = regTask.Run(null);
                    return runTask.State ;
    
                }
                catch (Exception ex)
                {
                    throw ex;
                }
    
            }
    View Code

    完整代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using TaskScheduler;
    
    namespace McodsBgManager
    {
        public class SchTaskExt
        {
            /// <summary>
            /// delete task
            /// </summary>
            /// <param name="taskName"></param>
            private static void DeleteTask(string taskName)
            {
                TaskSchedulerClass ts = new TaskSchedulerClass();
                ts.Connect(null, null, null, null);
                ITaskFolder folder = ts.GetFolder("\");
                folder.DeleteTask(taskName, 0);
            }
    
            /// <summary>
            /// get all tasks
            /// </summary>
            public static IRegisteredTaskCollection GetAllTasks()
            {
                TaskSchedulerClass ts = new TaskSchedulerClass();
                ts.Connect(null, null, null, null);
                ITaskFolder folder = ts.GetFolder("\");
                IRegisteredTaskCollection tasks_exists = folder.GetTasks(1);
                return tasks_exists;
            }
            /// <summary>
            /// check task isexists
            /// </summary>
            /// <param name="taskName"></param>
            /// <returns></returns>
             public static bool IsExists(string taskName)
            {
                var isExists = false;
                IRegisteredTaskCollection tasks_exists = GetAllTasks();
                for (int i = 1; i <= tasks_exists.Count; i++)
                {
                    IRegisteredTask t = tasks_exists[i];
                    if (t.Name.Equals(taskName))
                    {
                        isExists=true;
                        break;
                    }
                }
                return isExists;
            }
    
            /// <summary>
            /// create task
            /// </summary>
            /// <param name="creator"></param>
            /// <param name="taskName"></param>
            /// <param name="path"></param>
            /// <param name="interval"></param>
            /// <returns>state</returns>
             public static _TASK_STATE CreateTaskScheduler(string creator, string taskName, string path,string interval)
            {
                try
                {
                    if (IsExists(taskName))
                    {
                        DeleteTask(taskName);
                    }
    
                    //new scheduler
                    TaskSchedulerClass scheduler = new TaskSchedulerClass();
                    //pc-name/ip,username,domain,password
                    scheduler.Connect(null, null, null, null); 
                    //get scheduler folder
                    ITaskFolder folder = scheduler.GetFolder("\");
                    
    
                    //set base attr 
                    ITaskDefinition task = scheduler.NewTask(0);
                    task.RegistrationInfo.Author = "McodsAdmin";//creator
                    task.RegistrationInfo.Description = "...";//description
    
                    //set trigger  (IDailyTrigger ITimeTrigger)
                    ITimeTrigger tt = (ITimeTrigger)task.Triggers.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_TIME);
                    tt.Repetition.Interval = interval;// format PT1H1M==1小时1分钟 设置的值最终都会转成分钟加入到触发器
                    tt.StartBoundary = "2015-04-09T14:27:25";//start time
    
                    //set action
                    IExecAction action = (IExecAction)task.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC);
                    action.Path = path;
    
                    task.Settings.ExecutionTimeLimit = "PT0S"; //运行任务时间超时停止任务吗? PTOS 不开启超时
                    task.Settings.DisallowStartIfOnBatteries = false;//只有在交流电源下才执行
                    task.Settings.RunOnlyIfIdle = false;//仅当计算机空闲下才执行
    
                    IRegisteredTask regTask = folder.RegisterTaskDefinition(taskName, task,
                                                                        (int)_TASK_CREATION.TASK_CREATE, null, //user
                                                                        null, // password
                                                                        _TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN,
                                                                        "");
                    IRunningTask runTask = regTask.Run(null);
                    return runTask.State ;
    
                }
                catch (Exception ex)
                {
                    throw ex;
                }
    
            }
        }
    }
    View Code

    SchTaskExt.cs封装好了如何使用呢?

    btnSetup_Click的代码如下:此处使用的是calc.exe做例。

    private void btnSetup_Click(object sender, RoutedEventArgs e)
            {
                //创建者
                var creator = "Tonge";
                //计划任务名称
                var taskName = "CalcTask";
                //执行的程序路径
                var path = "C:\Windows\System32\calc.exe";
                //计划任务执行的频率 PT1M一分钟  PT1H30M 90分钟
                var interval = "PT1M";
                //开始时间 请遵循 yyyy-MM-ddTHH:mm:ss 格式
                var startBoundary = "2015-04-09T14:27:25";
                var description = "this is description";
                _TASK_STATE state = SchTaskExt.CreateTaskScheduler(creator, taskName, path, interval, startBoundary,description);
                if (state == _TASK_STATE.TASK_STATE_RUNNING)
                {
                    MessageBox.Show("计划任务部署成功!");
                }
            }

    运行成功后:

    可以看到calc.exe已经跑起来了,接下来我们在控制面板找到计划任务窗口看看。

    好了 大功告成!

    注意

    1.引用taskchd.dll后选中按下F4在属性中将 嵌入互操作类型 改为 False (没设置会报一个错误: 无法嵌入互操作类型“TaskScheduler.TaskSchedulerClass”。请改用适用的接口。 )

    2.所有操作都需要实例化schdule后进行connection:schdule.Connec("pc-name 或者 ip","username","domain","password")

    3.触发器类型有多种选择(按天IDailyTrigger,按分钟ITimeTrigger));

    触发频率(Interval)的格式需要遵循"PT1H1M"这样的格式;

    起始时间需要遵循"YYYY-MM-DDThh:mm:ss"这样的格式。

    4.计划任务运行的实例好像只能是唯一的,因为目前的情况这个calc可以正常运行第一次,第二次就被拒绝请求:

    操作员或系统管理员拒绝了请求。(0x800710E0) ,这个错误在网上并没有找到解决方案,如下图。

    后来在网上搜到 這里这种解决方案,但是按照设置后仍没得到解决,官方也没有这个错误代码(点击這里查看Task Scheduler)。

    所以我理解成这个计划任务只能运行一个实例,这个实例没有结束之前,如果到达下一次触发周期,则会被拒绝计划请求。

    另:如有其它诠释还请指明,非常感谢!

    完!

  • 相关阅读:
    使用ngx_lua构建高并发应用(1)
    nginx+lua项目学习
    学习乱
    if---(switch-case)语句初步学习总结
    数据类型转换
    总结:C#变量,占位符等相关知识
    学习随笔
    开始我的.NET的学习旅程
    Python 网络爬虫 008 (编程) 通过ID索引号遍历目标网页里链接的所有网页
    Python 网络爬虫 007 (编程) 通过网站地图爬取目标站点的所有网页
  • 原文地址:https://www.cnblogs.com/tonge/p/4410066.html
Copyright © 2011-2022 走看看