使用C#創建計划任務(How to create a Task Scheduler use C# )


本文主要講解了如何使用C#來創建windows計划任務。

 

  •  需求:在不定時間段運行多個后台程序(winfrom,wpf,console,等等)用於更新數據。
  •  問題:為什么要使用計划任務,而不直接在程序中使用一個計時器來觸發呢?

    •  答:最明顯的一點,使用計時器程序一直在后台運行着,但需求中只需要一天運行一次,或一個月運行一次。一直后台跑着計時這不白浪費CPU資源么。
  •  解決方案:
    • 使用windows自帶的計划任務 在控制面板中可以看到,手動新建計划任務。
    • 使用微軟自帶的類庫TaskScheduler("c:\windows\system32\taskchd.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)。

所以我理解成這個計划任務只能運行一個實例,這個實例沒有結束之前,如果到達下一次觸發周期,則會被拒絕計划請求。

 

另:如有其它詮釋還請指明,非常感謝!

 

完!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM