在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("刪除任務"); } }