在windows系统中,我们总能感受到一些开机或者登录后,就会弹出软件更新的小弹窗,或者其他软件弹出的各种小窗口。如何实现这种功能呢?
实现开机或者登录后检测更新、弹出小弹窗,有两种方法。一种是写一个小程序,然后加入到开机自启注册表中,让系统运行它;另一种是写一个任务计划程序,由它控制更新或者执行其他任务。
甚至,如果开机自启的小程序需要管理员权限运行,而程序又没有windows认证的安全证书,开机自启都不会启动它。但任务计划程序是直接运行这个程序的,即使需要管理员权限,因为创建任务计划程序本就需要管理员权限创建。
创建一个任务计划程序,很简单,首先需要我们引入一个Microsoft.Win32.TaskScheduler.dll(下载地址)。
引入dll后,我们需要用到TaskService类,它能够管理计算机上的服务。
1、TaskService的简单用法
/// <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(); }
2、创建一个任务计划程序
创建一个任务计划程序,首先需要获得当前计算机的任务计划程序集,然后定义一个任务。直接new一个TaskService对象,然后调用TaskService 对象的方法NewTask()获取到一个TaskDefinition的对象,该对象将是我们设置任务信息的核心操作者。
- TaskDefinition 的 RegistrationInfo,就是我们看到的任务里常规的显示信息,注入创建者、创建时间、版本、描述等等信息;
- TaskDefinition 的 Triggers 定义什么时候触发程序执行,开机后?登录后?还是延迟启动?等等不同的类型,这就是任务里的触发器。 不同的触发器,内容不一样(不详述),定义好Trigger,然后将对象加入TaskDefinition 的Triggers集合里。当然,一个任务也可以有多个触发器;
- TaskDefinition 的 Actions 将定义触发器触发后,执行什么操作,比如启动程序?下载数据?上报数据?还是其他的。同理,Action也可以有多个。
- TaskDefinition 的 Settings 可以配置任务的条件和设置。比如,某些操作必须要先接通电源。
- 最后,只需要调用TaskService的RootFolder.RegisterTaskDefinition,注册该任务对象,就可以了。
下面是我简单定义了一个用户登录则启动的一个示例:
/// <summary> /// 创建指定任务 /// </summary> /// <param name="taskName"></param> /// <param name="path"></param> /// <param name="description"></param> /// <param name="creator"></param> /// <param name="delay">延时启动时间</param> /// <returns></returns> public static TaskState CreateTaskScheduler(string taskName, string path, string description = "", string creator = "", 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; //开机自启 //BootTrigger bootTrigger = new BootTrigger(); //// bootTrigger.StartBoundary = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); //bootTrigger.Enabled = true; //if (delay.HasValue) //{ // bootTrigger.Delay = delay.Value; //} ////设置重复任务间隔时间 ////bootTrigger.Repetition.Interval = TimeSpan.FromDays(1); //td.Triggers.Add(bootTrigger); //用户登录时启动 LogonTrigger logonTrigger = new LogonTrigger(); //logonTrigger.StartBoundary = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); logonTrigger.Enabled = true; if (delay.HasValue) { logonTrigger.Delay = delay.Value; } //设置重复任务间隔时间 //logonTrigger.Repetition.Interval = TimeSpan.FromDays(1); definition.Triggers.Add(logonTrigger); definition.Actions.Add(new ExecAction(path, "", null)); definition.Principal.RunLevel = TaskRunLevel.Highest; definition.Principal.UserId = "Administrators"; 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, "Administrators", null, TaskLogonType.Group, ""); //task.Run(); return task.State; } catch (Exception ex) { throw ex; } }
3、创建一个任务
由于任务是可以绕开安全检查的,但创建一个任务是绕不开的,因此,创建一个任务,需要使用管理员权限。
首先,检测管理员权限,然后才是创建任务。
WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity);
bool isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
void CreateTask() { string taskName = "NigleAutoStart"; var creator = "Y&Z"; var path = @"D:WpfApp1.exe";//任务动作为启动D盘下的程序 var description = "开机自启"; Console.WriteLine("设置任务"); var state = SystemTaskScheduler.CreateTaskScheduler(taskName, path, description, creator); Console.WriteLine($"任务设置成功:{state}"); if (state == Microsoft.Win32.TaskScheduler.TaskState.Running) { System.Threading.Thread.Sleep(2000); SystemTaskScheduler.DeleteTask(taskName); Console.WriteLine("删除任务"); } }