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.
 
 
 
 
 

409 lines
16 KiB

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Transactions;
using System.Xml;
/*==================================================
* Name:定時執行任務
* Author:John.yuan
* Time:2015-01-08
* Modify:
====================================================*/
namespace TimingTask
{
public partial class TimingTaskService : ServiceBase
{
private string taskConnectionString;
private string logPath;
private long periodSecond;
private List<TimingTaskInfo> taskList;
/// <summary>
/// 構造函數
/// </summary>
public TimingTaskService()
{
InitializeComponent();
XmlDocument docConfig = new XmlDocument();
try
{
docConfig.Load(System.Environment.CurrentDirectory + "/TimingTaskConfig.xml");
XmlNodeList xnl = docConfig.SelectNodes(@"//Tasks");
foreach (XmlNode xn in xnl)
{
taskConnectionString = xn.Attributes["ConnectionString"].Value;
periodSecond = long.Parse(xn.Attributes["Period"].Value);
logPath = xn.Attributes["LogPath"].Value;
}
}
catch (Exception e)
{
WriteLog("TimingTaskService:" + e.Message);
}
}
/// <summary>
/// 初始化定時任務
/// </summary>
private void InitializeTimingTask()
{
XmlDocument docConfig = new XmlDocument();
docConfig.Load(System.Environment.CurrentDirectory + "/TimingTaskConfig.xml");
XmlNodeList xnl = docConfig.SelectNodes(@"//Task[@IsEnabled='Y']");
taskList = new List<TimingTaskInfo>();
foreach (XmlNode xn in xnl)
{
string taskID = xn.Attributes["ID"].Value;
string taskName = xn.Attributes["Name"].Value;
TaskType timingTaskType;
switch (xn.Attributes["TaskType"].Value)
{
case "M":
timingTaskType = TaskType.Month;
break;
case "D":
timingTaskType = TaskType.Day;
break;
case "W":
timingTaskType = TaskType.Week;
break;
case "P":
timingTaskType = TaskType.Period;
break;
default:
WriteLog("InitializeTimingTask:任務類型配置異常。");
continue;
}
DateTime beginTime;
DateTime endTime;
try
{
beginTime = AnalyzeTime(timingTaskType, xn.Attributes["BeginTime"].Value);
endTime = AnalyzeTime(timingTaskType, xn.Attributes["EndTime"].Value);
if (beginTime.Ticks >= endTime.Ticks)
{
WriteLog("InitializeTimingTask:開始時間或結束時間配置異常。");
continue;
}
}
catch (Exception e)
{
WriteLog("InitializeTimingTask:" + e.Message);
continue;
}
long period = long.Parse(xn.Attributes["Period"].Value);
if (beginTime.Ticks > DateTime.Now.Ticks || endTime.Ticks <= DateTime.Now.Ticks)
{
switch (timingTaskType)
{
case TaskType.Day:
beginTime = beginTime.AddDays(1);
endTime = endTime.AddDays(1);
break;
case TaskType.Month:
beginTime = beginTime.AddMonths(1);
endTime = endTime.AddMonths(1);
break;
case TaskType.Week:
beginTime = beginTime.AddDays(7);
endTime = endTime.AddDays(7);
break;
case TaskType.Period:
continue;
default:
WriteLog("InitializeTimingTask:任務類型配置異常。");
continue;
}
}
string className = xn.Attributes["ClassName"].Value;
string assemblyName = xn.Attributes["AssemblyName"].Value;
try
{
Assembly taskAssembly = Assembly.LoadFrom(System.Environment.CurrentDirectory + @"/LIB/" + assemblyName);
Type taskAssType = taskAssembly.GetType(className);
TimingTaskBase.TimingTaskBase timingObj = (TimingTaskBase.TimingTaskBase)Activator.CreateInstance(taskAssType);
TimingTaskInfo taskInfo = new TimingTaskInfo()
{
TaskID = taskID,
TaskName = taskName,
BeginTime = beginTime,
EndTime = endTime,
TaskType = timingTaskType,
TaskObject = timingObj,
Period = period,
LastCompleteTime = null
};
taskList.Add(taskInfo);
}
catch (Exception e)
{
WriteLog("InitializeTimingTask:" + e.Message);
}
}
}
protected override void OnStart(string[] args)
{
try
{
//初始化任務信息
InitializeTimingTask();
InitializeEachTaskTimer();
}
catch (Exception e)
{
WriteLog("OnStart:" + e.Message);
}
}
protected override void OnStop()
{
try
{
using (TransactionScope trans = new TransactionScope())
{
XmlDocument docConfig = new XmlDocument();
docConfig.Load(System.Environment.CurrentDirectory + "/TimingTaskConfig.xml");
foreach (TimingTaskInfo timingInfo in this.taskList)
{
timingInfo.TaskTimer.Change(-1, -1);
XmlNodeList xnl = docConfig.SelectNodes(@"//Tasks[@ID='" + timingInfo.TaskID + "']");
foreach (XmlNode xn in xnl)
{
XmlElement xmlEmt = (XmlElement)xn;
xmlEmt.SetAttribute("LastCompleteTime", timingInfo.LastCompleteTime.Value.ToString("yyyy-MM-dd HH:mm:ss"));
}
}
docConfig.Save(System.Environment.CurrentDirectory + "/TimingTaskConfig.xml");
trans.Complete();
}
}
catch (Exception e)
{
WriteLog("OnStop:" + e.Message);
}
}
/// <summary>
/// 計時器回呼函數
/// </summary>
/// <param name="state"></param>
protected void InitializeEachTaskTimer()
{
foreach (TimingTaskInfo timingInfo in this.taskList)
{
if (timingInfo.BeginTime.Ticks <= DateTime.Now.Ticks && DateTime.Now.Ticks < timingInfo.EndTime.Ticks)
{
try
{
if (timingInfo.LastCompleteTime == null || !timingInfo.LastCompleteTime.HasValue)
{
timingInfo.TaskTimer = new Timer(new TimerCallback(TaskExecute), timingInfo, 0, timingInfo.Period);
}
else
{
switch (timingInfo.TaskType)
{
case TaskType.Day:
if (timingInfo.LastCompleteTime.Value.Ticks < timingInfo.BeginTime.Ticks)
{
timingInfo.TaskTimer = new Timer(new TimerCallback(TaskExecute), timingInfo, 0, timingInfo.Period);
}
break;
case TaskType.Week:
if (timingInfo.LastCompleteTime.Value.Ticks < timingInfo.BeginTime.Ticks)
{
timingInfo.TaskTimer = new Timer(new TimerCallback(TaskExecute), timingInfo, 0, timingInfo.Period);
}
break;
case TaskType.Month:
if (timingInfo.LastCompleteTime.Value.Ticks < timingInfo.BeginTime.Ticks)
{
timingInfo.TaskTimer = new Timer(new TimerCallback(TaskExecute), timingInfo, 0, timingInfo.Period);
}
break;
case TaskType.Period:
timingInfo.TaskTimer = new Timer(new TimerCallback(TaskExecute), timingInfo, 0, timingInfo.Period);
break;
default:
WriteLog("任務配置資訊錯誤。");
break;
}
}
}
catch (Exception e)
{
WriteLog("CallEachTask:" + e.Message);
}
}
}
}
/// <summary>
/// 任務執行介面
/// </summary>
/// <param name="state"></param>
private void TaskExecute(object state)
{
using (TransactionScope trans = new TransactionScope())
{
try
{
TimingTaskInfo timingInfo = (TimingTaskInfo)state;
TimingTaskBase.TimingTaskBase timingBase = timingInfo.TaskObject;
timingBase.Run();
timingInfo.LastCompleteTime = DateTime.Now;
trans.Complete();
WriteLog(timingInfo.TaskName + ",執行成功。");
}
catch (Exception e)
{
WriteLog("TaskExecute:" + e.Message);
}
}
}
/// <summary>
/// 分析時間字串
/// </summary>
/// <param name="tkType"></param>
/// <param name="timeString"></param>
/// <returns></returns>
private DateTime AnalyzeTime(TaskType tkType, string timeString)
{
DateTime resultTime;
string[] timeArray = timeString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (timeArray.Length < 3 || timeArray.Length > 3)
{
throw new Exception("開始時間或結束時間參數設置錯誤。");
}
switch (tkType)
{
case TaskType.Day:
if ("*" == timeArray[1] || "*" == timeArray[2])
{
throw new Exception("開始時間或結束時間參數設置錯誤。");
}
else
{
resultTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, int.Parse(timeArray[1]), int.Parse(timeArray[2]), 0);
}
break;
case TaskType.Week:
if ("*" == timeArray[0] || "*" == timeArray[1] || "*" == timeArray[2])
{
throw new Exception("開始時間或結束時間參數設置錯誤。");
}
else
{
if ((int)DateTime.Now.DayOfWeek > int.Parse(timeArray[0]))
{
resultTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.AddDays(7 + int.Parse(timeArray[0]) - (int)DateTime.Now.DayOfWeek).Day, int.Parse(timeArray[1]), int.Parse(timeArray[2]), 0);
}
else if ((int)DateTime.Now.DayOfWeek < int.Parse(timeArray[0]))
{
resultTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.AddDays(int.Parse(timeArray[0]) - (int)DateTime.Now.DayOfWeek).Day, int.Parse(timeArray[1]), int.Parse(timeArray[2]), 0);
}
else
{
resultTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, int.Parse(timeArray[1]), int.Parse(timeArray[2]), 0);
}
}
break;
case TaskType.Month:
if ("*" == timeArray[0] || "*" == timeArray[1] || "*" == timeArray[2])
{
throw new Exception("開始時間或結束時間參數設置錯誤。");
}
else
{
if (DateTime.Now.Day > int.Parse(timeArray[0]))
{
resultTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.AddDays(-DateTime.Now.Day).AddMonths(1).AddDays(int.Parse(timeArray[0])).Day, int.Parse(timeArray[1]), int.Parse(timeArray[2]), 0);
}
else
{
resultTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, int.Parse(timeArray[0]), int.Parse(timeArray[1]), int.Parse(timeArray[2]), 0);
}
}
break;
case TaskType.Period:
if ("*" != timeArray[0] && "*" != timeArray[1] && "*" != timeArray[2])
{
resultTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, int.Parse(timeArray[0]), int.Parse(timeArray[1]), int.Parse(timeArray[2]), 0);
}
else if ("*" != timeArray[1] && "*" != timeArray[2])
{
resultTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, int.Parse(timeArray[1]), int.Parse(timeArray[2]), 0);
}
else if ("*" != timeArray[2])
{
resultTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, int.Parse(timeArray[2]), 0);
}
else
{
resultTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, 0);
}
break;
default:
resultTime = DateTime.Now;
break;
}
if (resultTime.Ticks > DateTime.Now.Ticks)
{
return resultTime;
}
else
{
return DateTime.Now;
}
}
/// <summary>
/// 寫定時任務日誌
/// </summary>
/// <param name="strMsg"></param>
private void WriteLog(string strMsg)
{
string strFile = logPath + @"/TimingTaskLog.log";
object objLock = new object();
if (!File.Exists(strFile))
{
File.Create(strFile);
}
lock (objLock)
{
StreamWriter sw = new StreamWriter(strFile, true);
sw.WriteLine(DateTime.Now.ToString());
sw.WriteLine("message text:" + strMsg);
sw.Close();
}
}
}
}