C# Windows 工作排程器 最簡單教學

又寫完一個小專案,回顧了一下發現還沒有寫過本次專案中也有使用到的「工作排程器」的相關文章,速速來把它補上

如果要自動觸發應用程式,除了把程式放在「啟動」資料夾讓開機自動啟動外,我們還可以透過 Windows 的工作排程器 (Task Scheduler) 1.0 和 2.0 提供的功能來達成許多更為進階的操作,例如基本的開機自動啟動(觸發)、定時觸發、閒置時觸發、事件觸發、註冊觸發、連接狀態改變觸發等等。

但這些好用的功能微軟並沒有提供 API 給 C# 呼叫,不過網路上的大神已經把它寫好打包完,所以我們在 C# 中也能很容易的開發。

安裝 TaskScheduler

先使用 NuGet 安裝 TaskScheduler 套件,或是使用 .NET CLI 執行以下指令安裝
	
dotnet add package TaskScheduler
    

TaskScheduler 使用時要在上方引用套件,引用的程式碼為:
    
using Microsoft.Win32.TaskScheduler;
    

如果網路上有人因為找不到 Microsoft.Win32.TaskScheduler 要安裝什麼套件而點進來的,希望能夠成功解決你的問題

自動啟動

這裡放一個實際範例:使用者登入時自動開啟檔案
    
using Microsoft.Win32.TaskScheduler;

TaskDefinition taskDefinition = TaskService.Instance.NewTask();
taskDefinition.RegistrationInfo.Description = "這是描述";
// taskDefinition.Principal.RunLevel = TaskRunLevel.Highest; // 工作管理員權限


LogonTrigger logonTrigger = new LogonTrigger(); // 登入觸發器
logonTrigger.Delay = TimeSpan.FromSeconds(10); // 延遲10秒執行

// 只有當前登入的使用者登入時才會觸發
string? userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
if (userName == null) throw new Exception("無法取得使用者名稱");
logonTrigger.UserId = userName;
taskDefinition.Triggers.Add(logonTrigger);

// 開啟檔案
taskDefinition.Actions.Add(new ExecAction(@"C:\Users\ruyut\Desktop\test.txt", null, null));
// 註冊任務
TaskService.Instance.RootFolder.RegisterTaskDefinition("使用者登入時自動開啟檔案", taskDefinition);
    


註:在上方程式碼(11~14 行)中很「麻煩」的讀取了當前的使用者名稱,設定為只有當前的使用者在未來登入時才會觸發,為什麼不直接設為所有使用者登入都會觸發呢?因為很麻煩且可能沒有必要。
如果超過當前使用者能做到的事情,例如指定其他使用者登入時也會觸發,那就需要系統管理員權限,開發人員需要請求提升權限、檢查當前是否有權限,如果啟動的目標程式是自己,那是不是每次自己被開啟都會再請求權限?會不會雖然設定開機自動啟動,但是因為要權限,卡在請求權限頁面等待使用者確認而導致應用程式無法順利執行?
當然好的設計可以只要第一次有請求權限之後就可以以系統管理員權限執行了,但是真的有必要讓每個使用者登入時都執行嗎?

如果你執意要讓所有使用者登入時都觸發,那只要把第 5 行取消註解、刪除第 11 ~ 14 行,然後讓使用者以系統管理員身分執行本程式即可,不過好的軟體設計就是需要盡可能的減少使用者的操作步驟、只使用必要的權限,畢竟我們也會是其他軟體的使用者!

參考資料:
Microsoft.Learn - 工作排程器腳本物件
Github - TaskScheduler
Github - TaskScheduler - TriggerSamples

留言