最近一直在處理不同專案的 CI/CD 作業,有個自動化排程作業就需要將應用程式註冊到 工作排程器 (Task Scheduler) 之中,因此就研究了一下如何利用 PowerShell 來完成這個自動化工作。
基本觀念
工作排程器 (Task Scheduler) 是 Windows 內建服務之一,可以用來控制在「指定時間或區間內」進行一連串的「工作」執行,這工作可能包含一些命令或應用程式執行。
基本上,工作排程器主要可以區分兩種「觸發條件」來啟動一份排程工作:
-
以時間為基礎的觸發條件 (time-based trigger)
你可以在特定時間點,或是特定時間區間,啟動一個或多個工作。可以只啟動一次工作,也可以週期性地啟動工作。
週期性的工作可以是每天、每周、每月、每年,而最短可從「每分鐘」啟動一次工作。
-
以事件為基礎的觸發條件 (event-based trigger)
你可以設定當系統發生特定事件時自動啟動工作,例如設定開機時、使用者登入時、工作站鎖定時、...等等,還可以設定事件記錄器中特定 事件來源 (Source) 或 事件編號 (Event ID) 發生時觸發。
一個「排程工作」可以設定多組「觸發條件」,任何一個觸發條件成立,就會立刻啟動工作,因此設定上非常具有彈性。例如:如果你想每隔 30 秒就執行一次工作,就可以設定兩組觸發條件,每一組都是設定「每分鐘」啟動一次,但是第一個觸發條件的開始時間可以設定為 12:00:00
、另一個觸發條件就可以設定為 12:00:30
,如此一來每次執行的間隔時間最小時間就可以設定到每隔 30 秒就執行一次!
基本範例
以下我對幾種常用的排程工作進行解說,解說完你就會比較清楚透過 PowerShell 建立工作的方法:
-
建立一個每天凌晨 4:00 執行一次的工作排程
一個排程工作是由「觸發條件」與「執行動作」所組成,因此要透過 PowerShell 建立排程工作,必須分別由 New-ScheduledTaskTrigger 與 New-ScheduledTaskAction 定義,並在取得物件之後透過 Register-ScheduledTask 註冊到工作排程器之中。
$STTrig = New-ScheduledTaskTrigger -Daily -At '4am'
$Action = New-ScheduledTaskAction -Execute '每日商品資料批次更新.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '每日商品資料批次更新' -Trigger $STTrig -Action $Action
Register-ScheduledTask -TaskName '每日商品資料批次更新' -Trigger $STTrig -Action $Action -Description ''
如果你要加上詳細的描述文字,可以在最後一個 Register-ScheduledTask
命令加上 -Description
參數:
Register-ScheduledTask -TaskName '每日商品資料批次更新' -Trigger $STTrig -Action $Action -Description '這裡可以撰寫所有跟每日商品資料批次更新的說明。'
-
刪除現有的工作排程
$taskName = '每日商品資料批次更新'
if (Get-ScheduledTask | Where-Object { $_.TaskName -eq $taskName }) {
Unregister-ScheduledTask $taskName -Confirm:$false
}
工作排程器的功能相當強大,因此使用案例非常多,完整的 Cmdlets 清單可以參考 ScheduledTasks 文件說明。
以時間為基礎的觸發條件 (time-based trigger)
以下我列出常用的 PowerShell 命令範例,大部分應該都非常淺顯易懂:
-
設定當天下午 3:00 只執行一次工作
$STTrig = New-ScheduledTaskTrigger -Once -At 3pm
$Action = New-ScheduledTaskAction -Execute '每日商品資料批次更新.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '每日商品資料批次更新' -Trigger $STTrig -Action $Action
如果在下午 3:00 之後才執行這個命令,這個工作就不會被自動執行
-
設定每天凌晨 2:00 自動執行工作
$STTrig = New-ScheduledTaskTrigger -Daily -At 2am
$Action = New-ScheduledTaskAction -Execute '每日商品資料批次更新.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '每日商品資料批次更新' -Trigger $STTrig -Action $Action
-
設定每天早上 6:00 與下午 6:00 個別執行一次工作
$STTrig = @(
$(New-ScheduledTaskTrigger -Daily -At '06:00'),
$(New-ScheduledTaskTrigger -Daily -At '18:00')
)
$Action = New-ScheduledTaskAction -Execute '每日商品資料批次更新.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '每日商品資料批次更新' -Trigger $STTrig -Action $Action
-
設定每隔 1 個小時自動執行工作
$STTrig = New-ScheduledTaskTrigger -Once -At 12am -RepetitionInterval (New-TimeSpan -Hours 1)
$Action = New-ScheduledTaskAction -Execute '每日商品資料批次更新.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '每日商品資料批次更新' -Trigger $STTrig -Action $Action
-
設定每隔 2 天的凌晨 3:00 自動執行工作
$STTrig = New-ScheduledTaskTrigger -Daily -At 03:00 -DaysInterval 2
$Action = New-ScheduledTaskAction -Execute '每日商品資料批次更新.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '每日商品資料批次更新' -Trigger $STTrig -Action $Action
-
設定每週週日的凌晨 3:00 自動執行工作
$STTrig =New-ScheduledTaskTrigger -Weekly -At 3am -DaysOfWeek Sunday
$Action = New-ScheduledTaskAction -Execute '每日商品資料批次更新.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '每日商品資料批次更新' -Trigger $STTrig -Action $Action
-
設定每間隔 1 週的週日 (兩週一次) 的凌晨 3:00 自動執行工作
$STTrig =New-ScheduledTaskTrigger -Weekly -At 3am -WeeksInterval 2 -DaysOfWeek Sunday
$Action = New-ScheduledTaskAction -Execute '每日商品資料批次更新.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '每日商品資料批次更新' -Trigger $STTrig -Action $Action
以事件為基礎的觸發條件 (event-based trigger)
以下我列出常用的 PowerShell 命令範例,大部分應該都非常淺顯易懂:
-
當使用者登入時執行
$STTrig = New-ScheduledTaskTrigger -AtLogon
$Action = New-ScheduledTaskAction -Execute '自動檢查代理程式更新.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '自動檢查代理程式更新' -Trigger $STTrig -Action $Action
-
當指定使用者登入時執行
$STTrig = New-ScheduledTaskTrigger -AtLogon -User 'ADName\Username'
$Action = New-ScheduledTaskAction -Execute '自動檢查代理程式更新.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '自動檢查代理程式更新' -Trigger $STTrig -Action $Action
-
當作業系統開機時執行
$STTrig = New-ScheduledTaskTrigger -AtStartup
$Action = New-ScheduledTaskAction -Execute '自動檢查代理程式更新.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '自動檢查代理程式更新' -Trigger $STTrig -Action $Action
關於執行身份與權限等級
你必須以系統管理員身份執行 PowerShell 才能執行以下命令:
-
使用當前使用者但透過 -RunLevel Highest
提高為以系統管理員身份執行工作
$STTrig = New-ScheduledTaskTrigger -AtLogon
$Action = New-ScheduledTaskAction -Execute '自動檢查代理程式更新.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '自動檢查代理程式更新' -Trigger $STTrig -Action $Action -RunLevel Highest
若要用 Unregister-ScheduledTask 刪除排程工作,也必須用相同的權限才能刪除。
-
使用 BUILTIN\Administrators
身份並以以系統管理員身份執行工作
$STTrig = New-ScheduledTaskTrigger -AtStartup
$STPrin = New-ScheduledTaskPrincipal -GroupId "BUILTIN\Administrators" -RunLevel Highest
$Action = New-ScheduledTaskAction -Execute '自動檢查代理程式更新.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '自動檢查代理程式更新' -Trigger $STTrig -Action $Action -Principal $STPrin
善加利用 -TaskPath
設定排程工作目錄
如果你一個專案有好幾個工作排程要設定,可以善加利用目錄的方式整理這些排程工作。
-
批次建立 3 個排程工作,並放在 電商背景工作排程
目錄下
$stt1 = New-ScheduledTaskTrigger -Once -At 3pm
$sta1 = New-ScheduledTaskAction -Execute '每日商品資料批次更新1.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '每日商品資料批次更新1' -TaskPath '電商背景工作排程' -Trigger $stt1 -Action $sta1
$stt2 = New-ScheduledTaskTrigger -Once -At 4pm
$sta2 = New-ScheduledTaskAction -Execute '每日商品資料批次更新2.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '每日商品資料批次更新2' -TaskPath '電商背景工作排程' -Trigger $stt2 -Action $sta2
$stt3 = New-ScheduledTaskTrigger -Once -At 5pm
$sta3 = New-ScheduledTaskAction -Execute '每日商品資料批次更新3.exe' -WorkingDirectory 'C:/Jobs'
Register-ScheduledTask -TaskName '每日商品資料批次更新3' -TaskPath '電商背景工作排程' -Trigger $stt3 -Action $sta3
-
批次刪除整個排程工作目錄
$folderName = '電商背景工作排程'
$tasks = Get-ScheduledTask | Where-Object { $_.TaskPath -eq "\$folderName\" }
foreach ($task in $tasks) {
Unregister-ScheduledTask $task.TaskName -Confirm:$false
}
照理說你只要執行以下兩個命令,就可以刪除排程工作目錄,但是工作排程目錄的 機碼(Registry) 我目前找不到刪除方法,會有權限不足的問題,所以目前只能開啟「工作排程器」應用程式來刪除目錄。
$folderName = '電商背景工作排程'
Remove-Item -Path "C:\Windows\System32\Tasks\$folderName"
Remove-Item -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\$folderName" -Force
相關連結