重要  本條目包含此範例腳本的文章已退休。 從 2026 年 5 月 12 日及之後發布的 Windows 更新開始,範例腳本位於您裝置的 %systemroot%\SecureBoot\ExampleRolloutScripts 資料夾中。

複製貼上這個範例腳本,並根據你的環境進行修改:

<# .劇情簡介     將安全啟動部署協調器作為 Windows 排程任務。

.DESCRIPTION     建立一個排程任務,讓編排器在背景持續執行。任務執行時會以繞過執行策略執行,因此不會出現安全提示。     策劃者將:     - 在指定區間內輪詢裝置更新     - 自動產生波次並部署 GPO     - 持續直到所有符合資格的裝置更新     為止     使用以下方法監控進度:Get-SecureBootRolloutStatus.ps1

.PARAMETER AggregationInputPath     UNC 從偵測 GPO) (的 JSON 裝置資料路徑

.PARAMETER ReportBasePath     報告與狀態檔案的本地路徑

.PARAMETER TargetOU     OU 連結 GPO (可選,預設為網域根)

.PARAMETER PollIntervalMinutes     狀態檢查之間的幾分鐘。 預設值:30

.PARAMETER UseWinCS     使用 Windows 組態系統) WinCS (取代 AvailableUpdatesPolicy GPO。啟用後,會將 WinCsFlags.exe 排程任務部署到端點,而非登錄檔 GPO。

.PARAMETER WinCSKey     WinCS 用於安全開機設定的金鑰。 預設:F33E0C8E002

.PARAMETER ServiceAccount     帳號來執行任務。 預設:系統     網域操作時,請使用網域管理員服務帳號。

.PARAMETER AllowListPath     包含主機名稱的檔案路徑,允許部署 (目標/試點部署) 。支援每行) .txt (一個主機名稱,.csv (欄位為 Hostname/ComputerName/Name 欄位) 。在指定時,只有這些裝置會納入推廣範圍。

.PARAMETER AllowADGroup     包含電腦帳號的 AD 安全群組名稱,允許。範例:「SecureBoot-Pilot-Computers」

.PARAMETER ExclusionListPath     包含主機名稱的檔案路徑,需排除 VIP/行政設備 () 。支援每行) .txt (一個主機名稱,.csv (欄位為 Hostname/ComputerName/Name 欄位) 。

.PARAMETER ExcludeADGroup     包含要排除的電腦帳號的 AD 安全群組名稱。範例:「VIP電腦」

.PARAMETER ScriptPath     通往編排器腳本的路徑。 預設值:與這個腳本相同的資料夾。

.PARAMETER Uninstall     移除排程任務

.EXAMPLE     .\Deploy-OrchestratorTask.ps1 -AggregationInputPath “\\server\SecureBootData$” - ReportBasePath “C:\SecureBootReports” - ServiceAccount “DOMAIN\svc_secureboot”

.EXAMPLE     .\Deploy-OrchestratorTask.ps1 -AggregationInputPath “\\server\SecureBootData$” -ReportBasePath “C:\SecureBootReports”

.EXAMPLE     # 使用 WinCS 方法部署,而非 AvailableUpdatesPolicy     .\Deploy-OrchestratorTask.ps1 -AggregationInputPath “\\server\SecureBootData$” - ReportBasePath “C:\SecureBootReports” - UseWinCS

.EXAMPLE     .\Deploy-OrchestratorTask.ps1 -卸載 #>

[CmdletBinding()] 參數 (     [參數 (強制 = $false) ]     [弦]$AggregationInputPath,          [參數 (強制 = $false) ]     [string]$ReportBasePath,          [參數 (強制 = $false) ]     [string]$TargetOU,          [參數 (強制 = $false) ]     [int]$PollIntervalMinutes = 30,          [參數 (強制 = $false) ]     [開關]$UseWinCS,          [參數 (強制 = $false) ]     [字串]$WinCSKey = 「F33E0C8E002」,          [參數 (強制 = $false) ]     [字串]$ServiceAccount = 「系統」,          [參數 (強制 = $false) ]     [string]$AllowListPath,          [參數 (強制 = $false) ]     [string]$AllowADGroup,          [參數 (強制 = $false) ]     [string]$ExclusionListPath,          [參數 (強制 = $false) ]     [string]$ExcludeADGroup,          [參數 (強制 = $false) ]     [string]$ScriptPath,          [參數 (強制 = $false) ]     [切換]$Uninstall )

$ErrorActionPreference = "Stop" $TaskName = 「SecureBoot-Rollout-Orchestrator」 $DownloadUrl = 「https://aka.ms/getsecureboot」 $DownloadSubPage = 「部署與監控樣本」

# ================================================================== # 依賴驗證# ==================================================================

function Test-ScriptDependencies {     <#     .劇情簡介         驗證所有必要的腳本都已具備。.描述         檢查腳本依賴性,若缺少則提供下載說明。#>     參數 (         [參數 (強制 = $true) ]         [string]$ScriptDirectory,                  [參數 (強制 = $true) ]         [string[]]$RequiredScripts     )          $missingScripts = @ ()          $RequiredScripts) 中每個 ($script {         $scriptPath = Join-Path $ScriptDirectory $script         如果 (-not (測試路徑$scriptPath) ) {             $missingScripts += $script         }     }          如果 ($missingScripts.Count -gt 0) {         Write-Host「」         Write-Host (“=” * 70) -前景紅色         Write-Host 「缺少依賴性」-前景紅色         Write-Host (“=” * 70) -前景紅色         Write-Host「」         Write-Host 「未找到以下所需的腳本:」-ForegroundColor Yellow         $missingScripts) 中每個 ($script {             Write-Host “ - $script” - 前景白色         }         Write-Host「」         Write-Host 「請下載最新腳本來源:」-ForegroundColor Cyan         Write-Host 「網址:$DownloadUrl」-前景白色         Write-Host 「導航至:『$DownloadSubPage』」-前景白色         Write-Host「」         Write-Host 「將所有腳本解壓到同一目錄,然後重新執行。」-ForegroundColor 黃色         Write-Host「」         $false     }          $true }

# Required scripts for orchestrator deployment $requiredScripts = @ (     「Start-SecureBootRolloutOrchestrator.ps1」,     「Aggregate-SecureBootData.ps1」,     「Deploy-GPO-SecureBootCollection.ps1」,     「Detect-SecureBootCertUpdateStatus.ps1」,     「Get-SecureBootRolloutStatus.ps1」,     「Enable-SecureBootUpdateTask.ps1」 )

if (-not (Test-ScriptDependencies -ScriptDirectory $PSScriptRoot -RequiredScripts $requiredScripts)) {     出口1 }

# ================================================================== # 解除安裝# ==================================================================

if ($Uninstall) {     Write-Host「」     Write-Host「移除排程任務:$TaskName」-前景色黃          $existingTask = Get-ScheduledTask -任務名稱 $TaskName -ErrorAction 靜默繼續     如果 ($existingTask) {         Stop-ScheduledTask -任務名稱 $TaskName -錯誤動作靜默繼續         Unregister-ScheduledTask -任務名稱 $TaskName -確認:$false         Write-Host「任務成功移除。」-前景綠色     } 否則 {         Write-Host「任務未找到。」-前景灰色     }     出口0 }

# ================================================================== # 驗證# ==================================================================

if (-not $AggregationInputPath -or -not $ReportBasePath) {     Write-Host 「錯誤:-AggregationInputPath 與 -ReportBasePath 是必需的。」-ForegroundColor Red     Write-Host「」     Write-Host 「範例:」-前景色 黃色     Write-Host ' .\Deploy-OrchestratorTask.ps1 -AggregationInputPath “\\server\SecureBootData$” -ReportBasePath “C:\SecureBootReports”'     出口1 }

# Find orchestrator script 如果 (-不$ScriptPath) {     $ScriptPath = Join-Path $PSScriptRoot「Start-SecureBootRolloutOrchestrator.ps1」 }

if (-not (Test-Path $ScriptPath)) {     Write-Host 「錯誤:找不到編排器腳本:$ScriptPath」-前景紅色     出口1 }

# Find aggregation script (needed by orchestrator) $aggregateScript = Join-Path $PSScriptRoot「Aggregate-SecureBootData.ps1」 如果 (-not (測試路徑$aggregateScript) ) {     Write-Host 「警告:Aggregate-SecureBootData.ps1 無法在腳本目錄中找到」-前景色黃     Write-Host「如果無法找到這個腳本,編排器可能會失敗。」——前景顏色:黃色 }

Write-Host "" Write-Host (“=” * 70) -前景色 青色 Write-Host 「安全啟動啟動協調器 - 任務部署」-前景青色 Write-Host (“=” * 70) -前景色 青色 Write-Host「」

# For display, show relative paths (script names only) $displayScriptPath = Split-Path $ScriptPath -葉片

Write-Host "Configuration:" -ForegroundColor Yellow Write-Host 「任務名稱:$TaskName」 Write-Host「指揮者:$displayScriptPath」 Write-Host 「輸入路徑:$AggregationInputPath」 Write-Host「報告路徑:$ReportBasePath」 Write-Host 「目標 OU: $ (如果 ($TargetOU) { $TargetOU } 否則 { ' (domain root) ' }) ” Write-Host 「投票間隔:$PollIntervalMinutes分鐘」 Write-Host 「服務帳號:$ServiceAccount」 Write-Host “部署方法:$ (如果 ($UseWinCS) { ”WinCS (WinCsFlags.exe) “ } 否則 { ”AvailableUpdatesPolicy (GPO) “ }) ” 如果 ($UseWinCS) {     Write-Host 「WinCS 按鍵:$WinCSKey」 } Write-Host「」

# ================================================================== # GPO 偵測 - 若未中 自動部署# ==================================================================

$CollectionGPOName = "SecureBoot-EventCollection" $deployGpoScript = Join-Path $PSScriptRoot「Deploy-GPO-SecureBootCollection.ps1」

# Check if GroupPolicy module is available 如果 (Get-Module -ListAvailable -Name GroupPolicy) {     Import-Module GroupPolicy -ErrorAction 靜默繼續          Write-Host「檢查偵測 GPO...」-ForegroundColor 黃色          試試看 {         # 從 AggregationInputPath 取得網域,例如 \\domain\share ()         $domainFromPath = 如果 ($AggregationInputPath 匹配 '^\\\\ ([^\\]+) \\') {             $matches[1]         } 否則 {             $env:USERDNSDOMAIN         }                  # 查查GPO是否存在         $existingGpo = Get-GPO -Name $CollectionGPOName -ErrorAction 靜默繼續                  如果 ($existingGpo) {             Write-Host 「偵測 GPO 已找到:$CollectionGPOName」-前景綠色         } 否則 {             Write-Host「」             Write-Host (“=” * 70) -前景色 黃色             Write-Host「偵測 GPO 未找到」-前景色:黃色             Write-Host (“=” * 70) -前景色 黃色             Write-Host「」             Write-Host「未找到偵測 GPO '$CollectionGPOName'」。-ForegroundColor Yellow             Write-Host「此 GPO 必須收集裝置狀態資料。」-前景黃色             Write-Host「」                          # 詢問使用者是否想現在部署 GPO             Write-Host「你現在想部署偵測 GPO 嗎? (Y/N) “ -前景 青色             $response = 讀取主機                          若 ($response -匹配 '^[Yy]') {                 Write-Host「」                 Write-Host 「啟動 GPO 部署中......」-ForegroundColor 青色                 Write-Host「」                                  # 建置 GPO 部署參數                 $gpoParams = @{                     網域名稱 = $domainFromPath                     CollectionSharePath = $AggregationInputPath                     ScriptSourcePath = Join-Path $PSScriptRoot 「Detect-SecureBootCertUpdateStatus.ps1」                 }                                  如果 ($TargetOU) {                     $gpoParams.OUPath = $TargetOU                 } 否則 {                     # 使用 AutoDetectOU 讓使用者選擇                     $gpoParams.自動偵測OU = $true                 }                                  # 執行 GPO 部署腳本                 & $deployGpoScript @gpoParams                                  若 ($LASTEXITCODE -ne 0) {                     Write-Host「GPO 部署可能遇到問題。 請檢視上方的輸出。」-前景色黃                     Write-Host「你可以繼續部署編排器,或按 Ctrl+C 中止。」-前景色黃                     Write-Host「」                     Read-Host「按 Enter 繼續」                 } 否則 {                     Write-Host「」                     Write-Host「偵測 GPO 成功部署!」-ForegroundColor Green                     Write-Host「」                 }             } 否則 {                 Write-Host「」                 Write-Host「跳過 GPO 部署。 編排器不會接收裝置資料」-前景色黃                 Write-Host「直到偵測 GPO 被手動部署為止。」-前景色黃                 Write-Host「」                 Write-Host 「稍後部署偵測 GPO,請執行:」-ForegroundColor 青色                 Write-Host “.\Deploy-GPO-SecureBootCollection.ps1 -網域名稱 '”$domainFromPath'“ -AutoDetectOU” -前景白色                 Write-Host「」             }         }     } 抓 {         Write-Host 「無法查詢GPO:$ ($_。例外。訊息) “ -前景顏色 黃色         Write-Host「繼續部署編排器......」-前景灰色     } } 否則 {     Write-Host「GroupPolicy 模組不可用 - 跳過 GPO 檢查」-前景顏色為灰色     Write-Host「確保偵測 GPO 是獨立部署的。」-Foreground Color Gray }

Write-Host ""

# ================================================================== # 建立論點# ==================================================================

$arguments = @(     「-無資料」     「-執行政策繞過」     「-檔案『$ScriptPath』」     「-AggregationInputPath '“$AggregationInputPath'”     「-報告BasePath '“$ReportBasePath'”     「-公投間隔分鐘$PollIntervalMinutes」 )

if ($TargetOU) {     $arguments += “-TargetOU '”$TargetOU'” }

if ($UseWinCS) {     $arguments += 「-UseWinCS」     $arguments += “-WinCSKey '”$WinCSKey'” }

if ($AllowListPath) {     $arguments += “-AllowListPath '”$AllowListPath'” }

if ($AllowADGroup) {     $arguments += “-AllowADGroup '”$AllowADGroup'” }

if ($ExclusionListPath) {     $arguments += “-ExclusionListPath '”$ExclusionListPath'” }

if ($ExcludeADGroup) {     $arguments += “-ExcludeADGroup '”$ExcludeADGroup'“” }

$argumentString = $arguments -join " "

# Don't display raw arguments with full paths - it's confusing for published scripts # 任務將內部使用完整路徑

# ================================================================== # 建立排程任務# ==================================================================

# Check for existing task $existingTask = Get-ScheduledTask -任務名稱 $TaskName -錯誤動作靜默繼續 如果 ($existingTask) {     Write-Host「任務已經存在。 更新中......」-前景顏色 黃色     Stop-ScheduledTask -任務名稱 $TaskName -錯誤動作 靜默繼續     Unregister-ScheduledTask -任務名稱 $TaskName -確認:$false }

# Create task action $action = New-ScheduledTaskAction -執行「powershell.exe」 -參數 $argumentString -WorkingDirectory $PSScriptRoot

# Create trigger - run once, immediately (orchestrator loops internally) $trigger = New-ScheduledTaskTrigger -一次 -在 (約會) 。AddMinutes (1)

# Create principal 若 ($ServiceAccount -eq 「系統」) {     $principal = New-ScheduledTaskPrincipal -UserID “NT AUTHORITY\SYSTEM” -LogonType ServiceAccount -RunLevel Highest } 否則 {     # 標準化本地帳號格式:COMPUTERNAME\User -> User     # Register-ScheduledTask 不接受本地帳號的 COMPUTERNAME\User 或 .\User     $taskUser = $ServiceAccount     如果 ($ServiceAccount -匹配 “^$ ([正則表達式]::Escape ($env:COMPUTERNAME) ) \\ (.+) $”) {         $taskUser = $Matches[1]         Write-Host 「注意:偵測到本地帳號,使用『$taskUser』來註冊任務」 -前景灰色     }

    # Prompt for password     Write-Host 「輸入密碼以$ServiceAccount」-前景色 黃色     $cred = Get-Credential -使用者名稱 $taskUser -訊息「排程任務的服務帳號憑證」     如果 (-不$cred) {         Write-Host「證件登錄取消。 中止。」-前景紅色         出口1     }     $principal = New-ScheduledTaskPrincipal -使用者ID $taskUser -登入類型密碼 -最高執行等級 }

# Task settings $settings = New-ScheduledTaskSettingsSet '     -允許啟動電池     -不要停下,如果要用電池     -有空就開始     -RunOnlyIfNetwork可用     -RestartCount 3 '     -RestartInterval (新時間跨度 -5分鐘) '     -執行時間限制 (新時間跨度 -30天) # 允許長時間運行

# Register task 試試看 {     若 ($ServiceAccount -eq 「系統」) {         Register-ScheduledTask -任務名稱 $TaskName -動作$action -觸發$trigger -主體$principal -設定 $settings -說明「安全啟動憑證推出 - 自動 GPO 部署」     } 否則 {         # 使用 New-ScheduledTask 將 RunLevel 最高) 的主要 (嵌入任務物件中,         # 然後註冊 -InputObject + -User/-Password (與 -Principal)         $taskDefinition = New-ScheduledTask -動作 $action -觸發 $trigger -主要 $principal -設定 $settings         $taskDefinition.Description = 「安全啟動憑證推出 - 自動 GPO 部署」         # 注意:Register-ScheduledTask 需要輸入純文字密碼 - 不存在 SecureString 過載         $netCred = $cred。GetNetworkCredential ()         Register-ScheduledTask -TaskName $TaskName -InputObject $taskDefinition -User $taskUser -Password $netCred.Password -ErrorAction 停止         $netCred = $null     }     Write-Host「排程任務成功建立!」-ForegroundColor Green } 抓 {     Write-Host 「無法建立排程任務:$ ($_。例外。訊息) “ -前景紅色     出口1 }

# ================================================================== # 建立狀態捷徑# ==================================================================

$statusScript = Join-Path $PSScriptRoot "Get-SecureBootRolloutStatus.ps1" 若 (測試路徑$statusScript) {     Write-Host「」     Write-Host 「要查詢推出狀態,請執行:」-前景色為黃色     Write-Host “.\Get-SecureBootRolloutStatus.ps1 -ReportBasePath '”$ReportBasePath'“ -ForegroundColor 青色 }

# ================================================================== # 輸出# ==================================================================

Write-Host "" Write-Host (“=” * 70) -前景綠色 Write-Host 「部署完成」-前景綠色 Write-Host (“=” * 70) -前景綠色 Write-Host「」 Write-Host「配器大約一分鐘後開始。」-前景白色 Write-Host「」 Write-Host 「監控中」:-前景色 黃色 Write-Host 「查看任務狀態:Get-ScheduledTask -任務名稱 '$TaskName' |選擇州」 Write-Host 「查看任務日誌:Get-Content '$ReportBasePath\RolloutState\Orchestrator_$ (Get-Date -格式 'yyyyMMdd') .log' -Tail 50” Write-Host 「檢視推出狀態:Get-Content '$ReportBasePath\RolloutState\RolloutState.json' |ConvertFrom-Json” Write-Host 「檢視儀表板:開始 '$ReportBasePath\Aggregation_*\SecureBoot_Dashboard*.html'」 Write-Host「快速狀態:.\Get-SecureBootRolloutStatus.ps1 -ReportBasePath '$ReportBasePath'」 Write-Host「」 Write-Host 「管理:」-前景色 黃色 Write-Host 「手動啟動:Start-ScheduledTask -任務名稱 '$TaskName'」 Write-Host 「停止:Stop-ScheduledTask -任務名稱 '$TaskName'」 Write-Host 「移除:.\Deploy-OrchestratorTask.ps1 -卸載」 Write-Host「」 ​​​​​​​

Need more help?

Want more options?

探索訂閱權益、瀏覽訓練課程、瞭解如何保護您的裝置等等。