static ExeStatus PerTime(TaskItem task, List <ProcessItem> processes, StringBuilder msg) { ExeStatus status; // 未设置定时运行参数时 if (!task.TaskPara.Any()) { status = ExeStatus.NoPara; // 更新任务运行状态 Dal.Default.UpdateTaskExeStatus(task.id, status); msg.Append("\r\n\t任务参数未配置,运行失败"); Utils.Output(msg.ToString()); return(status); } if (processes.Count <= 0) { status = ExeStatus.Stopped; } else { foreach (ProcessItem item in processes) { msg.AppendFormat("\r\n\t\t{0}", item); } status = ExeStatus.Running; } StringBuilder sbEndTime = new StringBuilder(); var now = DateTime.Now; bool? isrun = null; foreach (TimePara timepara in task.TaskPara) { if (task.runtype == RunType.PerWeek && timepara.WeekOrDay != (int)now.DayOfWeek) { continue; } if (task.runtype == RunType.PerMonth && timepara.WeekOrDay != now.Day) { continue; } // 启动小时必须是小于24的数,否则会出异常 int hour = timepara.StartHour;// == 24 ? 0 : timepara.StartHour; if (hour < 0) { hour = 0; } else if (hour >= 24) { hour = 0; } int min = timepara.StartMin; if (min > 59) { min = 59; } else if (min < 0) { min = 0; } DateTime starttime = new DateTime(now.Year, now.Month, now.Day, hour, min, 0); if (timepara.StartHour >= 24) { starttime = starttime.AddDays(1); } DateTime endtime = DateTime.MaxValue; // 为true表示启动时间是从数据库获取的 bool isTimeParaSeted = false; if (timepara.RunMinute > 0) { // 从数据库取得记录的结束时间(之所以保存到数据库,因为每次任务都是从db取得,每次StartTime都会被重置,导致隔日停止失败) timepara.StartTime = Dal.Default.GetTimePara(task.id, timepara); if (timepara.StartTime == default(DateTime)) { timepara.StartTime = starttime; } else { isTimeParaSeted = true; } endtime = timepara.StartTime.AddMinutes(timepara.RunMinute); sbEndTime.Append("\r\n\t" + timepara.StartTime.ToString("MM-dd_HH:mm") + "~" + endtime.ToString("MM-dd_HH:mm")); } // 任务已经处理过了 if (isrun != null) { continue; } // 前次运行时间比定时小 且 时间到了 且 进程没有运行 且 没过结束时间 //if (starttime > task.pidtime && starttime <= now && now < endtime) // 在启动时间之后,且在1分钟之内,启动它 if (starttime <= now && now < endtime && (now - starttime).TotalSeconds < 60) { isrun = true; // 记录开始时间,以便下次轮询判断结束 if (isTimeParaSeted) { Dal.Default.DelTimePara(task.id, timepara); } Dal.Default.AddTimePara(task.id, timepara); if (processes.Count <= 0) { var lastRunDiffSecond = (now - task.pidtime).TotalSeconds; if (lastRunDiffSecond > 60) { // 启动进程 var pid = ProcessHelper.CheckAndStartProcess(task.exepath, task.exepara); if (pid > 0) { task.NewPid = pid; msg.Append("任务成功启动,pid:" + pid.ToString()); } else { msg.Append("任务存在,启动失败"); } status = ExeStatus.Running; } else { msg.Append("\r\n\t任务1分钟只能启动1次"); status = ExeStatus.Stopped; } } else { msg.Append("\r\n\t" + processes.Count.ToString() + "个任务运行中"); status = ExeStatus.Running; } // 记录之,用于计算结束时间 if (timepara.RunMinute > 0) { timepara.StartTime = now; } // 不用break,是为了统计并输出结束时间日志 continue; } // now比endtime大,且在1分钟之内,停止它 if (endtime <= now && (now - endtime).TotalSeconds < 60 && processes.Count > 0) { isrun = false; // 结束完成,删除 开始时间记录,以便下次轮询重新计算 if (isTimeParaSeted) { Dal.Default.DelTimePara(task.id, timepara); } var killNum = ProcessHelper.KillProcesses(processes); if (killNum > 0) { msg.Append("\r\n\t任务成功终止" + killNum.ToString() + "个"); status = ExeStatus.Stopped; } else { msg.Append("\r\n\t任务终止失败"); } // 不用break,是为了统计并输出结束时间日志 //continue; } else if (endtime <= now && isTimeParaSeted) { // 清除上次启动时间,避免过期时间在以前,导致程序永远无法终止 Dal.Default.DelTimePara(task.id, timepara); } } if (isrun == null) { msg.Append("\r\n\t时间没到 " + (status == ExeStatus.Stopped ? "任务未启动" : "任务运行中")); } if (sbEndTime.Length > 0) { msg.Append("\r\n\t起止时间:" + sbEndTime); } Utils.Output(msg); return(status); }
/// <summary> /// 对程序立即进行的启动或停止操作 /// </summary> /// <param name="strArgs"></param> /// <returns></returns> static string ImmediateProcess(string strArgs) { // string args = ((int) type).ToString() + "\n" + path + "\n" + exepara; string[] args = strArgs.Split('\n'); if (args.Length < 3) { return("参数不足3个"); } int imtype; if (!int.TryParse(args[0], out imtype)) { return("无效的临时类型"); } string exepath = args[1]; // 防止出现 c:\\\\a.exe 或 c:/a.exe这样的路径,统一格式化成:c:\a.exe形式 exepath = Path.Combine(Path.GetDirectoryName(exepath) ?? "", Path.GetFileName(exepath) ?? ""); if (exepath.IndexOf('/') < 0 && exepath.IndexOf('\\') < 0) { string tmp = FindExeFromAllJob(exepath); if (string.IsNullOrEmpty(tmp)) { return("未找到对应job:" + exepath); } exepath = tmp; } if (!File.Exists(exepath)) { return("文件不存在:" + exepath); } string exepara = args[2]; int ret; switch ((ImmediateType)imtype) { default: return("不存在的临时类型"); case ImmediateType.Start: // 查找进程是否运行中,不在则启动 ret = ProcessHelper.CheckAndStartProcess(exepath, exepara); if (ret > 0) { return(exepath + " 成功启动, pid:" + ret.ToString()); } else { return(exepath + " 运行中,无需启动"); } case ImmediateType.Stop: var processes1 = ProcessItem.GetProcessByPath(exepath); ret = ProcessHelper.KillProcesses(processes1); // 有时间,应该改造成事件模式,发事件给消费者 TaskAutoRunService.AddStopJob(exepath); if (ret > 0) { return(exepath + " 成功关闭个数:" + ret.ToString()); } else { return(exepath + " 未运行,无需停止"); } case ImmediateType.ReStart: string restartMsg; // 杀死进程 var processes2 = ProcessItem.GetProcessByPath(exepath); ret = ProcessHelper.KillProcesses(processes2); if (ret > 0) { restartMsg = exepath + " 成功关闭个数:" + ret.ToString(); } else { restartMsg = exepath + " 未启动"; } // 查找进程是否运行中,不在则启动 ret = ProcessHelper.CheckAndStartProcess(exepath, exepara); if (ret > 0) { return(restartMsg + " 重启完成,pid:" + ret.ToString()); } else { return(restartMsg + " 进程已存在"); } } }
static void RunTaskFinish(List <TaskItem> tasks, List <ProcessItem> processesBefore) { #if DEBUG var end = DateTime.Now; #endif var processesLater = ProcessItem.GetProcessesAndCache(false); foreach (TaskItem task in tasks) { var proBefore = ProcessHelper.FilterByPath(processesBefore, task.exepath); var proLater = ProcessHelper.FilterByPath(processesLater, task.exepath); var pidBefore = new StringBuilder(); var pidEnd = new StringBuilder(); foreach (var processItem in proBefore) { pidBefore.AppendFormat("{0},", processItem.pid.ToString()); } var taskNewPidFinded = false; foreach (var processItem in proLater) { if (task.NewPid > 0 && processItem.pid == task.NewPid) { taskNewPidFinded = true; } pidEnd.AppendFormat("{0},", processItem.pid.ToString()); } var noFindAndLog = (task.NewPid > 0 && !taskNewPidFinded); // Utils.Output(task.exepath+"\r\n"+pidBefore + "\r\n" + pidEnd + "\r\n" + task.NewPid, "aa"); // 运行时的进程不见了,或 前后的pid不同了 if (noFindAndLog || pidBefore.ToString() != pidEnd.ToString()) { // 更新任务的pid var newpid = proLater.Count > 0 ? proLater[0].pid : 0; Dal.Default.UpdateTaskProcessId(task.id, newpid); if (pidBefore.Length > 0) { pidBefore.Insert(0, "; 运行前pid:"); } if (pidEnd.Length > 0) { pidBefore.AppendFormat("; 运行中pid:{0}", pidEnd); } if (noFindAndLog) { pidBefore.AppendFormat("; 运行中pid{0} 已自动退出", task.NewPid.ToString()); } var pidMsg = task.runtype.ToString() + pidBefore; Dal.Default.AddTaskLog(task.exepath, pidMsg); } } #if DEBUG // 输出任务执行前后的进程情况 var procMsg = new StringBuilder(); // procMsg.AppendFormat("执行前:{0}\r\n", begin.ToString("HH:mm:ss.fff")); foreach (var processItem in processesBefore.OrderBy(item => item.exePath)) { procMsg.AppendFormat("{0} {1}\r\n", processItem.pid.ToString(), processItem.exePath); } procMsg.AppendFormat("执行后:{0}\r\n", end.ToString("HH:mm:ss.fff")); foreach (var processItem in processesLater.OrderBy(item => item.exePath)) { procMsg.AppendFormat("{0} {1}\r\n", processItem.pid.ToString(), processItem.exePath); } Utils.Output(procMsg.ToString(), "process"); #endif }