有两种方式可以创建Windows计划任务程序
- bat脚本命令schtasks /create根据模板来创建计划任务
- 使用微软提供的Microsoft.Win32.TaskScheduler进行创建计划任务
两者的创建互有优劣:
bat脚本创建可以根据模板创建,比较简单方便;但是无法创建触发器需要特定用户,并且该用户设置了密码。(例如:触发器是A账户登录时,并且A账户有密码)
Microsoft.Win32.TaskScheduler创建计划任务比较复杂,但是可以创建触发器的特定用户设置了密码。
先介绍第一种bat脚本创建方式:
- 先手动在Windows任务计划程序——创建任务——手动把需要的任务AAA创建好
- 在C:\Windows\System32\Tasks中,找到AAA的文件复制出来,并且把名字改成AAA.xml。文件头必须是utf-16,不然创建任务时会提示读取xml失败
<?xml version="1.0" encoding="UTF-16"?>
- 然后使用bat将xml模板的操作替换成特定的操作(例如执行某个exe),bat替换xml字符串可以参考我的另一篇文章:使用bat操作替换XML文件的字符串
- 使用schtasks /create命令创建
rem 根据模板来创建计划任务
schtasks /create /ru "%UserId%" /rp "" /tn "%TaskName%" /xml "%XmlName%" /F
其中/ru 表示使用指定用户帐户的权限运行任务。/rp 指定的用户帐户的密码。 /tn 任务名称。 /xml xml模板文件(如果模板不在同一目录,需要完整路径)。 /f 如果指定的任务已经存在,则指定创建任务并取消警告。
接着介绍第二种使用Microsoft.Win32.TaskScheduler创建方式:
public class SystemTaskScheduler
{
/// <summary>
/// 获取所有任务
/// </summary>
public static TaskCollection GetAllTasks()
{
TaskService ts = new TaskService();
var folder = ts.GetFolder("\\");
var tasks_exists = folder.GetTasks();
folder.Dispose();
ts.Dispose();
return tasks_exists;
}
/// <summary>
/// 检查任务是否存在
/// </summary>
/// <param name="taskName"></param>
/// <returns></returns>
public static bool IsExists(string taskName)
{
var isExists = false;
TaskCollection tasks_exists = GetAllTasks();
for (int i = 0; i < tasks_exists.Count; i++)
{
var task = tasks_exists[i];
if (task.Name.Equals(taskName))
{
isExists = true;
break;
}
}
return isExists;
}
/// <summary>
/// 删除指定任务
/// </summary>
/// <param name="taskName"></param>
public static void DeleteTask(string taskName)
{
TaskService ts = new TaskService();
var folder = ts.GetFolder("\\");
folder.DeleteTask(taskName);
folder.Dispose();
ts.Dispose();
}
/// <summary>
/// 创建指定任务
/// </summary>
/// <param name="taskName"></param>
/// <param name="path"></param>
/// <param name="userId"></param>
/// <param name="description"></param>
/// <param name="creator"></param>
/// <param name="delay">延时启动时间</param>
/// <returns></returns>
public static bool CreateTaskScheduler(string taskName, string path, string userId, string creator = "", string description = "", TimeSpan? delay = null)
{
try
{
if (IsExists(taskName))
{
DeleteTask(taskName);
}
TaskService service = new TaskService();
TaskDefinition definition = service.NewTask();
definition.RegistrationInfo.Author = creator;
definition.RegistrationInfo.Description = description;
definition.RegistrationInfo.Version = new Version(1, 0, 0);
definition.RegistrationInfo.Date = DateTime.Now;
//会话改变
SessionStateChangeTrigger sessionStateChangeTrigger = new SessionStateChangeTrigger();
sessionStateChangeTrigger.StateChange = TaskSessionStateChangeType.SessionUnlock;
// 这里不需要特定账户的密码
sessionStateChangeTrigger.UserId = userId;
definition.Triggers.Add(sessionStateChangeTrigger);
//用户登录时启动
LogonTrigger logonTrigger = new LogonTrigger();
logonTrigger.Enabled = true;
logonTrigger.UserId = userId;
if (delay.HasValue)
{
logonTrigger.Delay = delay.Value;
}
definition.Triggers.Add(logonTrigger);
definition.Actions.Add(new ExecAction(path, "", null));
definition.Principal.RunLevel = TaskRunLevel.Highest;
definition.Principal.UserId = userId;
definition.Principal.LogonType = TaskLogonType.InteractiveToken;
//td.Settings.ExecutionTimeLimit = ; //运行任务时间超时停止任务吗?
definition.Settings.DisallowStartIfOnBatteries = false;//只有在交流电源下才执行
definition.Settings.RunOnlyIfIdle = false;//仅当计算机空闲下才执行
definition.Settings.Enabled = true;
definition.Settings.AllowDemandStart = true;
definition.Settings.AllowHardTerminate = true;
var task = service.RootFolder.RegisterTaskDefinition(taskName, definition,
TaskCreation.CreateOrUpdate,
userId, null,
TaskLogonType.None,
"");
//task.Run();
return true;
}
catch (Exception ex)
{
H3CLog.Error(ex);
return false;
}
}
}
题外话:Windows任务计划程序的一些注意事项
- 多个触发器是或的关系
- 触发器“启动时”,重启和关机启动都不起作用