原始出版日期: 2025年11月17日
KB ID:5072718
|
變更日期 |
變更描述 |
|
2026年2月24日 |
|
|
2026年2月22日 |
|
|
2026年2月13日 |
|
安全啟動庫存資料收集腳本範例
複製貼上此範例腳本,並依照您的環境進行修改:Sample Secure Boot Inventory Data Collection 腳本。
<# .劇情簡介 偵測安全開機憑證更新狀態,以進行全艦隊監控。
.描述 此偵測腳本會收集安全開機狀態、憑證更新登錄檔值, 以及裝置資訊。 它會輸出一個 JSON 字串用於監控和報告。
相容於 Intune Remediations、基於 GPO 的收集及其他管理工具。不需要修復處方——這只是監控而已。
出口 0 = 「無問題」 (更新憑證) 出口 1 = 「有問題」 (憑證未更新 — 僅提供資訊)
.參數輸出路徑 可選的。 一個資料夾的路徑,JSON 檔案會被儲存。如果有提供,會將HOSTNAME_latest.json儲存到這個資料夾。如果沒有提供,會輸出 JSON 來定速 (原始行為) 。
.範例 # 輸出到標準 (Intune/SCCM偵測) .\Detect-SecureBootCertUpdateStatus.ps1
.範例 # 儲存到網路分享 (GPO 部署) .\Detect-SecureBootCertUpdateStatus.ps1 -OutputPath “\\server\SecureBootLogs$”
.註釋 每 https://aka.ms/securebootplaybook 登錄路徑: HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing
軟體以「現狀」提供,不提供任何形式的保證,明確或 默示,包括但不限於可售性保證, 適合特定用途及不侵權。 無論如何,絕不會 作者或著作權持有人對任何索賠、損害或其他事項負責 責任,無論是契約訴訟、侵權或其他形式,均源自以下情況, 無論是與軟體本身、使用或其他交易有關 軟體。#> 參數 ( [參數 (強制 = $false) ] [string]$OutputPath )
# 下載 URL:https://aka.ms/getsecureboot ->「部署與監控樣本」 # 注意:此腳本會在端點上執行以收集安全開機狀態資料。
# 1. 主機名稱 # PS 版本:全部 |管理員:不 |系統需求:無 試試看 { $hostname = $env:COMPUTERNAME 如果 ([string]::IsNullOrEmpty ($hostname) ) { Write-Warning「主機名稱無法確定」 $hostname = 「未知」 } Write-Host「主機名稱:$hostname」 } 抓 { Write-Warning 「錯誤取得主機名稱:$_」 $hostname = 「錯誤」 Write-Host 「主機名稱:$hostname」 }
# 2. 收集時間 # PS 版本:全部 |管理員:不 |系統需求:無 試試看 { $collectionTime = 取得日期 若 ($null -eq $collectionTime) { Write-Warning「無法取得當前日期/時間」 $collectionTime = 「未知」 } Write-Host「收集時間:$collectionTime」 } 抓 { Write-Warning「錯誤取回日期/時間:$_」 $collectionTime = 「錯誤」 Write-Host「採集時間:$collectionTime」 }
# 登錄檔:安全開機主金鑰 (3 個值)
# 3. SecureBootEnabled # PS版本:3.0+ |管理員:可能需要 |系統需求:支援 UEFI/安全開機的系統 試試看 { $secureBootEnabled = Confirm-SecureBootUEFI -錯誤行動停止 Write-Host「啟用安全開機:$secureBootEnabled」 } 抓 { Write-Warning「無法透過 cmdlet 判斷安全開機狀態:$_」 # 試試登記後備 試試看 { $regValue = Get-ItemProperty -路徑「HKLM:\SYSTEM\CurrentControlSet\Control\Control\SecureBoot\State」 -名稱 UEFISecureBootEnabled -ErrorAction 停止 $secureBootEnabled = [bool]$regValue.UEFISecureBootEnabled Write-Host「安全開機啟用:$secureBootEnabled」 } 抓 { Write-Warning「無法透過登錄檔判斷安全開機狀態。 系統可能不支援 UEFI/安全開機。」 $secureBootEnabled = $null Write-Host「安全開機啟用:不可用」 } }
# 4. HighConfidenceOptOut # PS 版本:全部 |管理員:可能需要 |系統需求:無 試試看 { $regValue = Get-ItemProperty -路徑「HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot」-名稱 HighConfidenceOptOut -ErrorAction 停止 $highConfidenceOptOut = $regValue.HighConfidenceOptOut Write-Host「高信心選擇退出:$highConfidenceOptOut」 } 抓 { # HighConfidenceOptOut 是可選的——大多數系統不存在 $highConfidenceOptOut = $null Write-Host「高信心選擇退出:未設定」 }
# 4b。 MicrosoftUpdateManagedOptIn # PS 版本:全部 |管理員:可能需要 |系統需求:無 試試看 { $regValue = Get-ItemProperty -Path “HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot” -name MicrosoftUpdateManagedOptIn -ErrorAction Stop $microsoftUpdateManagedOptIn = $regValue.MicrosoftUpdateManagedOptIn Write-Host「Microsoft更新管理選擇加入:$microsoftUpdateManagedOptIn」 } 抓 { # MicrosoftUpdateManagedOptIn 是可選的——大多數系統不存在 $microsoftUpdateManagedOptIn = $null Write-Host「Microsoft 更新管理中的選擇加入:未設定」 }
# 5. 可用更新 # PS 版本:全部 |管理員:可能需要 |系統需求:無 試試看 { $regValue = Get-ItemProperty -路徑「HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot」-Name AvailableUpdates -ErrorAction 停止 $availableUpdates = $regValue.可用更新 如果 ($null -ne $availableUpdates) { # 轉換為十六進位格式 $availableUpdatesHex = “0x{0:X}” -f $availableUpdates Write-Host 「可用匯報:$availableUpdatesHex」 } 否則 { Write-Host 「可用匯報:不可用」 } } 抓 { Write-Warning 「AvailableUpdates 登錄檔金鑰未找到或無法存取」 $availableUpdates = $null Write-Host「可用匯報:不可用」 }
# 5b。 AvailableUpdatesPolicy (GPO 控制的持久值) # PS 版本:全部 |管理員:可能需要 |系統需求:無 試試看 { $regValue = Get-ItemProperty -路徑「HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot」-Name AvailableUpdatesPolicy -ErrorAction 停止 $availableUpdatesPolicy = $regValue.AvailableUpdatesPolicy 如果 ($null -ne $availableUpdatesPolicy) { # 轉換為十六進位格式 $availableUpdatesPolicyHex = “0x{0:X}” -f $availableUpdatesPolicy Write-Host「可用匯報保單:$availableUpdatesPolicyHex」 } 否則 { Write-Host「可用匯報政策:未設定」 } } 抓 { # AvailableUpdatesPolicy 為可選,僅在 GPO 套用時設定 $availableUpdatesPolicy = $null Write-Host「可用匯報政策:未設定」 }
# 登錄:服務金鑰 (3 個值)
# 6. UEFICA2023 狀態 # PS 版本:全部 |管理員:可能需要 |系統需求:無 試試看 { $regValue = Get-ItemProperty -路徑「HKLM:\SYSTEM\CurrentControlSet\Control\Control\SecureBoot\Servicing」 -名稱 UEFICA2023Status -ErrorAction 停止 $uefica 2023Status = $regValue.UEFICA2023Status Write-Host 「Windows UEFI CA 2023 狀態:$uefica 2023 狀態」 } 抓 { Write-Warning 「Windows UEFI CA 2023 狀態登錄檔金鑰未找到或無法存取」 $uefica 2023年狀態 = $null Write-Host 「Windows UEFI CA 2023 狀態:無法使用」 }
# 7. UEFICA2023 錯誤 # PS 版本:全部 |管理員:可能需要 |系統需求:無 試試看 { $regValue = Get-ItemProperty -路徑「HKLM:\SYSTEM\CurrentControlSet\Control\Control\SecureBoot\Servicing」 -名稱 UEFICA2023Error -ErrorAction 停止 $uefica 2023Error = $regValue.UEFICA2023Error Write-Host 「UEFI CA 2023 錯誤:$uefica 2023Error」 } 抓 { # UEFICA2023錯誤只有在有錯誤時才存在——缺席是好事 $uefica 2023Error = $null Write-Host 「UEFI CA 2023 錯誤:無」 }
# 8. UEFICA2023ErrorEvent # PS 版本:全部 |管理員:可能需要 |系統需求:無 試試看 { $regValue = Get-ItemProperty -路徑「HKLM:\SYSTEM\CurrentControlSet\Control\Control\SecureBoot\Servicing」 -名稱 UEFICA2023ErrorEvent -ErrorAction 停止 $uefica 2023ErrorEvent = $regValue.UEFICA2023ErrorEvent Write-Host 「UEFI CA 2023 錯誤事件:$uefica 2023ErrorEvent」 } 抓 { $uefica 2023ErrorEvent = $null Write-Host「UEFI CA 2023 錯誤事件:不可用」 }
# 登錄檔:裝置屬性 (7 個值:9-15)
# 9. OEMManufacturerName # PS 版本:全部 |管理員:可能需要 |系統需求:無 試試看 { $regValue = Get-ItemProperty -路徑 “HKLM:\SYSTEM\CurrentControlSet\Control\Control\SecureBoot\Servicing\DeviceAttributes” -Name OEMManufacturerName -ErrorAction 停止 $oemManufacturerName = $regValue.OEMManufacturerName 如果 ([string]::IsNullOrEmpty ($oemManufacturerName) ) { Write-Warning 「OEMManufacturerName 是空的」 $oemManufacturerName = 「未知」 } Write-Host 「原廠製造商名稱:$oemManufacturerName」 } 抓 { Write-Warning 「OEMManufacturerName 登錄檔金鑰未找到或無法存取」 $oemManufacturerName = $null Write-Host 「原廠製造商名稱:無法取得」 }
# 10. OEMModelSystemFamily # PS 版本:全部 |管理員:可能需要 |系統需求:無 試試看 { $regValue = Get-ItemProperty -路徑「HKLM:\SYSTEM\CurrentControlSet\Control\Control\SecureBoot\Servicing\DeviceAttributes」-名稱 OEMModelSystemFamily -ErrorAction 停止 $oemModelSystemFamily = $regValue.OEMModelSystemFamily 如果 ([string]::IsNullOrEmpty ($oemModelSystemFamily) ) { Write-Warning 「OEMModelSystemFamily 是空的」 $oemModelSystemFamily = 「未知」 } Write-Host 「OEM 型號系統家族:$oemModelSystemFamily」 } 抓 { Write-Warning 「OEMModelSystemFamily 登錄金鑰未找到或無法存取」 $oemModelSystemFamily = $null Write-Host 「OEM 系統系列:無法取得」 }
# 11. OEMModel編號 # PS 版本:全部 |管理員:可能需要 |系統需求:無 試試看 { $regValue = Get-ItemProperty -路徑「HKLM:\SYSTEM\CurrentControlSet\Control\Control\SecureBoot\Servicing\DeviceAttributes」-名稱 OEMModelNumber -ErrorAction 停止 $oemModelNumber = $regValue.OEMModelNumber 如果 ([string]::IsNullOrEmpty ($oemModelNumber) ) { Write-Warning「OEMModelNumber 是空的」 $oemModelNumber = 「未知」 } Write-Host 「原廠型號:$oemModelNumber」 } 抓 { Write-Warning 「OEMModelNumber 登錄金鑰未找到或無法存取」 $oemModelNumber = $null Write-Host 「原廠型號:無法取得」 }
# 12. 韌體版本 # PS 版本:全部 |管理員:可能需要 |系統需求:無 試試看 { $regValue = Get-ItemProperty -路徑「HKLM:\SYSTEM\CurrentControlSet\Control\Control\SecureBoot\Servicing\DeviceAttributes」 -Name FirmwareVersion -ErrorAction 停止 $firmwareVersion = $regValue.FirmwareVersion 如果 ([string]::IsNullOrEmpty ($firmwareVersion) ) { Write-Warning「韌體版本為空」 $firmwareVersion = 「未知」 } Write-Host 「韌體版本:$firmwareVersion」 } 抓 { Write-Warning「找不到或無法存取韌體版本登錄鍵」 $firmwareVersion = $null Write-Host 「韌體版本:無法使用」 }
# 13. 韌體發行日期 # PS 版本:全部 |管理員:可能需要 |系統需求:無 試試看 { $regValue = Get-ItemProperty -路徑「HKLM:\SYSTEM\CurrentControlSet\Control\Control\SecureBoot\Servicing\DeviceAttributes」 -名稱 FirmwareReleaseDate -ErrorAction 停止 $firmwareReleaseDate = $regValue.FirmwareReleaseDate 如果 ([string]::IsNullOrEmpty ($firmwareReleaseDate) ) { Write-Warning「韌體發布日期為空」 $firmwareReleaseDate = 「未知」 } Write-Host 「韌體發行日期:$firmwareReleaseDate」 } 抓 { Write-Warning 「FirmwareReleaseDate 登錄金鑰未找到或無法存取」 $firmwareReleaseDate = $null Write-Host 「韌體發行日期:無法取得」 }
# 14. OSArchitecture # PS 版本:全部 |管理員:不 |系統需求:無 試試看 { $osArchitecture = $env:PROCESSOR_ARCHITECTURE 如果 ([string]::IsNullOrEmpty ($osArchitecture) ) { # 試試登記後備 $regValue = Get-ItemProperty -路徑「HKLM:\SYSTEM\CurrentControlSet\Control\Control\SecureBoot\Servicing\DeviceAttributes」-名稱 OSArchitecture -ErrorAction 停止 $osArchitecture = $regValue.OSArchitecture } 如果 ([string]::IsNullOrEmpty ($osArchitecture) ) { Write-Warning 「OSArchitecture無法確定」 $osArchitecture = 「未知」 } Write-Host 「作業系統架構:$osArchitecture」 } 抓 { Write-Warning 「錯誤取回 OSArchitecture: $_」 $osArchitecture = 「未知」 Write-Host 「作業系統架構:$osArchitecture」 }
# 15. CanAttemptUpdate (FILETIME) # PS 版本:全部 |管理員:可能需要 |系統需求:無 試試看 { $regValue = Get-ItemProperty -路徑「HKLM:\SYSTEM\CurrentControlSet\Control\Control\SecureBoot\Servicing\DeviceAttributes」-Name CanAttemptUpdateAfter -ErrorAction 停止 $canAttemptUpdateAfter = $regValue.CanAttemptUpdateAfter # 將 FILETIME 轉換為 UTC DateTime — 登錄檔儲存為 REG_BINARY (位元組[]) 或長 REG_QWORD (長) 若 ($null -ne $canAttemptUpdateAfter) { 試試看 { 若 ($canAttemptUpdateAfter -是 [byte[]]) { $fileTime = [BitConverter]::ToInt64 ($canAttemptUpdateAfter, 0) $canAttemptUpdateAfter = [DateTime]::FromFileTime ($fileTime) 。致環球時 () } elseif ($canAttemptUpdateAfter -is [長]) { $canAttemptUpdateAfter = [DateTime]::FromFileTime ($canAttemptUpdateAfter) 。致環球時 () } } 抓 { Write-Warning 「無法將 CanAttemptUpdateAfter FILETIME 轉換為 DateTime」 } } Write-Host「可嘗試更新:$canAttemptUpdateAfter」 } 抓 { Write-Warning「CanAttemptUpdateAfter 登錄檔金鑰未找到或無法存取」 $canAttemptUpdateAfter = $null Write-Host「可嘗試更新:無法使用」 }
# 事件日誌:系統日誌 (10 個值:16-25)
# 16-25. 事件日誌查詢 # 活動編號: # 1801 - 更新啟動,需重啟 # 1808 - 更新成功完成 # 1795 - 韌體回傳錯誤 (擷取錯誤代碼) # 1796 - 錯誤記錄,包含錯誤代碼 (擷取代碼) # 1800 - 需要重啟 (非錯誤 - 重新啟動後更新將持續) # 1802 - 已知韌體問題被阻擋更新 (擷取 SkipReason KI_<>) # 1803 - 未找到匹配的 KEK 更新 (OEM 需要提供 PK 簽名的 KEK) # PS版本:3.0+ |管理員:可能需要用於系統日誌 |系統需求:無 試試看 { # 查詢所有相關的安全啟動事件 ID $allEventIds = @ (1795、1796、1800、1801、1802、1803、1808) $events = @ (Get-WinEvent -FilterHashtable @{LogName='System';ID=$allEventIds} -MaxEvents 50 -ErrorAction 停止)
如果 ($events。計數 -eq 0) { Write-Warning 「系統日誌中未發現安全開機事件」 $latestEventId = $null $bucketId = $null $confidence = $null $skipReasonKnownIssue = $null $event 1801 計數 = 0 $event 1808 計數 = 0 $event 1795 計數 = 0 $event 1795ErrorCode = $null $event 1796年計數 = 0 $event 1796ErrorCode = $null $event 1800計數 = 0 $rebootPending = $false $event 1802 計數 = 0 $knownIssueId = $null $event 1803 計數 = 0 $missingKEK = $false Write-Host「最新事件ID:無法取得」 Write-Host 「桶 ID:無法使用」 Write-Host 「信心:無法取得」 Write-Host 「事件1801 計數:0」 Write-Host 「事件1808 計數:0」 } 否則 { # 16. 最新事件ID $latestEvent = $events |Sort-Object 時間創造 -下降 |Select-Object -第一位 若 ($null -eq $latestEvent) { Write-Warning「無法確定最新事件」 $latestEventId = $null Write-Host 「最新事件 ID:無法取得」 } 否則 { $latestEventId = $latestEvent.Id Write-Host「最新事件ID:$latestEventId」 }
# 17. BucketID - 摘自事件 1801/1808 如果 ($null -ne $latestEvent -且 $null -ne $latestEvent.訊息) { 如果 ($latestEvent.Message -match 'BucketId:\s* (.+) ') { $bucketId = $matches[1]。修剪 () Write-Host「桶ID:$bucketId」 } 否則 { Write-Warning「事件訊息中找不到 BucketId」 $bucketId = $null Write-Host 「桶 ID:事件中找不到」 } } 否則 { Write-Warning「最新事件或訊息為空,無法擷取 BucketId」 $bucketId = $null Write-Host 「桶 ID:無法使用」 }
# 18. 信心 - 摘自事件1801/1808 如果 ($null -ne $latestEvent -且 $null -ne $latestEvent.訊息) { 如果 ($latestEvent.Message -match 'BucketConfidenceLevel:\s* (.+) ') { $confidence = $matches[1]。修剪 () Write-Host 「信心:$confidence」 } 否則 { Write-Warning 「事件訊息中找不到信心水準」 $confidence = $null Write-Host 「自信:事件中找不到」 } } 否則 { Write-Warning「最新事件或訊息為空,無法取得信心」 $confidence = $null Write-Host 「信心:不可得」 }
# 18b。 SkipReason - 在與 BucketId 相同事件中從 SkipReason 中擷取KI_<數字> # 此資料捕捉與 BucketId/Confidence 並列出現的已知議題 ID, (不僅是事件 1802) $skipReasonKnownIssue = $null 若 ($null -ne $latestEvent -且 $null -ne $latestEvent.訊息) { if ($latestEvent.Message -match 'SkipReason:\s* (KI_\d+) ') { $skipReasonKnownIssue = $matches[1] Write-Host「SkipReason 已知問題:$skipReasonKnownIssue」-前景色:黃色 } }
# 19. 事件1801伯爵 $event 1801Array = @ ($events |Where-Object {$_.ID -eq 1801}) $event 1801Count = $event 1801Array.Count Write-Host 「事件1801年計數:$event 1801年計數」
# 20. 事件1808伯爵 $event 1808Array = @ ($events |Where-Object {$_.ID -eq 1808}) $event 1808Count = $event 1808Array.Count Write-Host 「事件1808計數:$event 1808計數」 # 初始化錯誤事件變數 $event 1795 計數 = 0 $event 1795ErrorCode = $null $event 1796 計數 = 0 $event 1796ErrorCode = $null $event 1800計數 = 0 $rebootPending = $false $event 1802 計數 = 0 $knownIssueId = $null $event 1803 計數 = 0 $missingKEK = $false # 只有在更新未完成時才檢查錯誤事件 # 跳過錯誤分析:1808 是最新事件或 UEFICA2023Status 為「更新」 $updateComplete = ($latestEventId -eq 1808) -or ($uefica 2023Status -eq 「更新」) 如果 (-不$updateComplete) { Write-Host「更新未完成 - 檢查錯誤事件......」-ForegroundColor Yellow # 21. Event1795 - 韌體錯誤 (擷取錯誤代碼) $event 1795Array = @ ($events |Where-Object {$_.ID -eq 1795}) $event 1795Count = $event 1795 Array.Count 如果 ($event 1795Count -gt 0) { $latestEvent 1795 = $event 1795 陣列 |Sort-Object 時間創造 -下降 |Select-Object -第一 if ($latestEvent 1795.Message -match ' (?:error|code|status) [:\s]* (?:0x) ? ([0-9A-Fa-f]{8}|[0-9A-Fa-f]+) ') { $event 1795ErrorCode = $matches[1] } Write-Host 「事件 1795 (韌體錯誤) 計數:$event 1795Count」$ (若 ($event 1795ErrorCode) { 「代碼:$event 1795ErrorCode」}) } # 22. Event1796 - 錯誤代碼已登錄 (擷取錯誤代碼) $event 1796Array = @ ($events |Where-Object {$_.ID -eq 1796}) $event 1796Count = $event 1796Array.Count 若 ($event 1796Count -gt 0) { $latestEvent 1796 = $event 1796 陣列 |Sort-Object 時間創造 -下降 |Select-Object -第一 if ($latestEvent 1796.Message -match ' (?:error|code|status) [:\s]* (?:0x) ? ([0-9A-Fa-f]{8}|[0-9A-Fa-f]+) ') { $event 1796ErrorCode = $matches[1] } Write-Host 「事件 1796 (錯誤記錄) 計數:$event 1796Count」 $ (如果 ($event 1796ErrorCode) { 「代碼:$event 1796ErrorCode」}) } # 23. Event1800 - 需要重開機 (不是錯誤 - 重新啟動後更新會繼續) $event 1800Array = @ ($events |Where-Object {$_.ID -eq 1800}) $event 1800Count = $event 1800Array.Count $rebootPending = $event 1800 計數 -gt 0 如果 ($rebootPending) { Write-Host「事件 1800 (重啟待定) :更新將在重啟後繼續」-ForegroundColor 青色 } # 24. Event1802 - 已知韌體問題 (從 SkipReason 擷取KI_<號碼>) $event 1802Array = @ ($events |Where-Object {$_.ID -eq 1802}) $event 1802Count = $event 1802Array.Count 如果 ($event 1802Count -gt 0) { $latestEvent 1802 = $event 1802 陣列 |Sort-Object 時間創造 -下降 |Select-Object -第一 如果 ($latestEvent 1802.訊息匹配 'SkipReason:\s* (KI_\d+) ') { $knownIssueId = $matches[1] } Write-Host 「事件 1802 (已知韌體問題) 計數:$event 1802Count」 $ (若 ($knownIssueId) { 「KI: $knownIssueId」}) } # 25. Event1803 - 缺少 KEK 更新 (OEM 需要提供 PK 簽署的 KEK) $event 1803Array = @ ($events |Where-Object {$_.ID -eq 1803}) $event 1803Count = $event 1803Array.Count $missingKEK = $event 1803 計數 -gt 0 如果 ($missingKEK) { Write-Host 「事件 1803 (缺少 KEK) :OEM 需要提供 PK 簽名的 KEK」-ForegroundColor Yellow } } 否則 { Write-Host 「事件 1808 或 Status=更新 () - 跳過錯誤分析」-前景綠色 } } } 抓 { Write-Warning「取得事件日誌時出錯。 可能需要管理員權限:$_” $latestEventId = $null $bucketId = $null $confidence = $null $skipReasonKnownIssue = $null $event 1801 計數 = 0 $event 1808年計數 = 0 $event 1795年計數 = 0 $event 1795ErrorCode = $null $event 1796計數 = 0 $event 1796ErrorCode = $null $event 1800計數 = 0 $rebootPending = $false $event 1802 計數 = 0 $knownIssueId = $null $event 1803 計數 = 0 $missingKEK = $false Write-Host 「最新事件 ID:錯誤」 Write-Host「桶 ID:錯誤」 Write-Host 「信心:錯誤」 Write-Host 「事件1801 計數:0」 Write-Host 「事件1808 計數:0」 }
# WMI/CIM 查詢 (5 個值)
# 26. OS的 # PS 版本:3.0+ (2.0 版本使用 Get-WmiObject) |管理員:不 |系統需求:無 試試看 { $osInfo = Get-CimInstance Win32_OperatingSystem -錯誤行動停止 若 ($null -eq $osInfo -或 [string]::IsNullOrEmpty ($osInfo.版本) ) { Write-Warning「無法取得作業系統版本」 $osVersion = 「未知」 } 否則 { $osVersion = $osInfo.版本 } Write-Host 「作業系統版本:$osVersion」 } 抓 { # CIM 在某些環境下可能會失敗 - 請使用備援 $osVersion = [System.Environment]::OSVersion.Version.ToString () 若 ([string]::IsNullOrEmpty ($osVersion) ) { $osVersion = 「未知」} Write-Host 「作業系統版本:$osVersion」 }
# 27. 最後啟動時間 # PS 版本:3.0+ (2.0 版本使用 Get-WmiObject) |管理員:不 |系統需求:無 試試看 { $osInfo = Get-CimInstance Win32_OperatingSystem -錯誤行動停止 如果 ($null -eq $osInfo -或 $null -eq $osInfo.LastBootUpTime) { Write-Warning「無法恢復上次開機時間」 $lastBootTime = $null Write-Host「最後開機時間:無法使用」 } 否則 { $lastBootTime = $osInfo.LastBootUpTime(最後啟動時間) Write-Host「最後一次開機時間:$lastBootTime」 } } 抓 { # CIM 在某些環境下可能會失敗 - 請使用備援 試試看 { $lastBootTime = (get-process -id 0 -errorAction 靜默繼續) 。開始時間 } 抓 { $lastBootTime = $null } 如果 ($lastBootTime) { Write-Host「最後開機時間:$lastBootTime」} 否則 { Write-Host「最後開機時間:不可用」} }
# 28. 踢腳板製造商 # PS 版本:3.0+ (2.0 版本使用 Get-WmiObject) |管理員:不 |系統需求:無 試試看 { $baseBoard = Get-CimInstance Win32_BaseBoard -錯誤動作停止 若 ($null -eq $baseBoard -或 [string]::IsNullOrEmpty ($baseBoard.Manufacturer) ) { Write-Warning 「無法取得踢腳板製造商」 $baseBoardManufacturer = 「未知」 } 否則 { $baseBoardManufacturer = $baseBoard。製造商 } Write-Host 「踢腳板製造商:$baseBoardManufacturer」 } 抓 { # CIM 可能失效 - 底板資訊為補充 $baseBoardManufacturer = 「未知」 Write-Host「踢腳板製造商:$baseBoardManufacturer」 }
# 29. BaseBoardProduct # PS 版本:3.0+ (2.0 版本使用 Get-WmiObject) |管理員:不 |系統需求:無 試試看 { $baseBoard = Get-CimInstance Win32_BaseBoard -錯誤動作停止 若 ($null -eq $baseBoard -或 [string]::IsNullOrEmpty ($baseBoard.Product) ) { Write-Warning「無法取回踢腳板產品」 $baseBoardProduct = 「未知」 } 否則 { $baseBoardProduct = $baseBoard.積 } Write-Host 「踢腳板產品:$baseBoardProduct」 } 抓 { # CIM 可能失效 - 底板資訊為補充 $baseBoardProduct = 「未知」 Write-Host 「踢腳板產品:$baseBoardProduct」 }
# 30. SecureBootTaskEnabled # PS 版本:全部 |管理員:不 |系統需求:已存在排程任務 # 檢查安全開機更新排程任務是否啟用 $secureBootTaskEnabled = $null $secureBootTaskStatus = 「未知」 試試看 { $taskOutput = schtasks.exe /查詢 /TN “\Microsoft\Windows\PI\Secure-Boot-Update” /FO CSV 2>&1 若 ($LASTEXITCODE -eq 0) { $taskData = $taskOutput |ConvertFrom-Csv 如果 ($taskData) { $secureBootTaskStatus = $taskData。狀態 $secureBootTaskEnabled = ($taskData.Status -eq 「準備好」 -或 $taskData.Status -eq 「運行中」) } } 否則 { $secureBootTaskStatus = 「未找到」 $secureBootTaskEnabled = $false } 若 ($secureBootTaskEnabled -eq $false) { Write-Host 「SecureBoot Update 任務:$secureBootTaskStatus (啟用:$secureBootTaskEnabled) 」-ForegroundColor Yellow } 否則 { Write-Host 「SecureBoot Update 任務:$secureBootTaskStatus (啟用:$secureBootTaskEnabled) 」 -前景綠色 } } 抓 { $secureBootTaskStatus = 「錯誤」 $secureBootTaskEnabled = $false Write-Host 「SecureBoot 更新任務:錯誤檢查 - $_」 -ForegroundColor Red }
# 31. WinCS 金鑰狀態 (F33E0C8E002 - 安全開機憑證更新) # PS 版本:全部 |管理員:是的,查詢) (|系統需求:WinCsFlags.exe $wincsKeyApplied = $null $wincsKeyStatus = 「未知」 試試看 { # 檢查常見地點 WinCsFlags.exe $wincsFlagsPath = $null $possiblePaths = @ ( 「$env:SystemRoot\System32\WinCsFlags.exe」, 「$env:SystemRoot\SysWOW64\WinCsFlags.exe」 ) foreach ($p in $possiblePaths) { 若 (測試路徑$p) { $wincsFlagsPath = $p; 中斷 } } 如果 ($wincsFlagsPath) { # 查詢特定金鑰 - 需要管理員權限 $queryOutput = & $wincsFlagsPath /query --key F33E0C8E002 2>&1 $queryOutputStr = $queryOutput -加入「'n」 若 ($LASTEXITCODE -eq 0) { # 檢查是否已啟用按鍵 (尋找「Active Configuration」或類似的指示) 如果 ($queryOutputStr -匹配「Active Configuration.*:.*enabled」 -或 $queryOutputStr -match 「Configuration.*applied」) { $wincsKeyApplied = $true $wincsKeyStatus = 「應用」 Write-Host「WinCS 鍵F33E0C8E002:已套用」-前景綠色 } elseif ($queryOutputStr -match 「未找到|「無配置」) { $wincsKeyApplied = $false $wincsKeyStatus = 「未申請」 Write-Host 「WinCS 金鑰F33E0C8E002:未套用」-foregroundColor Yellow } 否則 { # 鍵存在 - 檢查輸出狀態 $wincsKeyApplied = $true $wincsKeyStatus = 「應用」 Write-Host 「WinCS Key F33E0C8E002: 已套用」-foregroundColor Green } } 否則 { # 檢查特定錯誤訊息 如果 ($queryOutputStr -匹配「Access denied|administrator」) { $wincsKeyStatus = 「拒絕存取」 Write-Host 「WinCS 金鑰F33E0C8E002:存取被拒絕 (以管理員) 執行」-ForegroundColor DarkGray } elseif ($queryOutputStr -match 「未找到|「無配置」) { $wincsKeyApplied = $false $wincsKeyStatus = 「未適用」 Write-Host 「WinCS 金鑰F33E0C8E002:未套用」-前景色:黃色 } 否則 { $wincsKeyStatus = “QueryFailed” Write-Host 「WinCS Key F33E0C8E002:查詢失敗」-ForegroundColor Red } } } 否則 { $wincsKeyStatus = 「WinCsFlagsNotFound」 Write-Host 「WinCS Key F33E0C8E002:WinCsFlags.exe 找不到」-ForegroundColor Gray } } 抓 { $wincsKeyStatus = 「錯誤」 Write-Host 「WinCS 金鑰F33E0C8E002:錯誤檢查 - $_」 -ForegroundColor Red }
# ============================================================================= # 修復偵測 - 狀態輸出 & 退出碼 # =============================================================================
# 從所有收集的庫存資料中建立狀態物件 $status = [有序]@{ UEFICA2023Status = $uefica 2023Status UEFICA2023Error = $uefica 2023Error UEFICA2023ErrorEvent = $uefica 2023ErrorEvent AvailableUpdates = if ($null -ne $availableUpdates) { $availableUpdatesHex } else { $null } AvailableUpdatesPolicy = if ($null -ne $availableUpdatesPolicy) { $availableUpdatesPolicyHex } else { $null } 主機名稱 = $hostname CollectionTime = 如果 ($collectionTime -是 [datetime]) { $collectionTime.ToString (“o”) } 否則 { “$collectionTime” } SecureBootEnabled = $secureBootEnabled HighConfidenceOptOut = $highConfidenceOptOut MicrosoftUpdateManagedOptIn = $microsoftUpdateManagedOptIn OEMManufacturerName = $oemManufacturerName OEMModelSystemFamily = $oemModelSystemFamily OEMModelNumber = $oemModelNumber FirmwareVersion = $firmwareVersion FirmwareReleaseDate = $firmwareReleaseDate OSArchitecture = $osArchitecture CanAttemptUpdateAfter = 如果 ($canAttemptUpdateAfter -is [datetime]) { $canAttemptUpdateAfter.ToString (“o”) } 否則 { “$canAttemptUpdateAfter” } LatestEventId = $latestEventId BucketId = $bucketId 信心 = $confidence SkipReasonKnownIssue = $skipReasonKnownIssue # KI_<BucketId 事件中 SkipReason 的數字> 事件1801計數 = $event 1801計數 Event1808Count = $event 1808 Count # 錯誤事件與捕捉細節 Event1795Count = $event 1795Count # Firmware 返回錯誤 Event1795ErrorCode = $event 1795ErrorCode # 來自韌體的錯誤代碼 Event1796Count = $event 1796Count # 已記錄錯誤代碼 Event1796ErrorCode = $event 1796ErrorCode # 擷取錯誤碼 Event1800Count = $event 1800Count # 需要重啟 (不是錯誤) RebootPending = $rebootPending # 若事件 1800 存在則為真 Event1802Count = $event 1802Count # 已知韌體問題 KnownIssueID = $knownIssueId # KI_<> 來自 SkipReason Event1803Count = $event 1803Count # 缺少 KEK 更新 MissingKEK = $missingKEK # OEM 需要提供 PK 簽名的 KEK OSVersion = $osVersion LastBootTime = 如果 ($lastBootTime -is [datetime]) { $lastBootTime.ToString (“o”) } 否則 { “$lastBootTime” } 底板製造商 = $baseBoardManufacturer BaseBoardProduct = $baseBoardProduct SecureBootTaskEnabled = $secureBootTaskEnabled SecureBootTaskStatus = $secureBootTaskStatus WinCSKeyApplied = $wincsKeyApplied # 若套用F33E0C8E002鍵則為真 WinCSKeyStatus = $wincsKeyStatus # 已套用、未適用、WinCsFlagsNotFound,等等。 }
# 輸出狀態 - 用於資料聚合 $jsonOutput = $status |ConvertTo-Json -壓縮
# 若提供 OutputPath,則儲存至檔案;否則輸出至 stdout 如果 (-not [string]::IsNullOrEmpty ($OutputPath) ) { # 驗證 OutputPath - 如果看起來像是幫助請求或有無效字元,請跳過 如果 ($OutputPath -匹配 '^[/\-]' -或 $OutputPath -匹配 '[<>:“|?*]') { Write-Host 「指定無效輸出路徑,輸出至標準配置」-前景色黃色 Write-Output $jsonOutput 如果 ($secureBootEnabled -和 $uefica 2023Status -eq “Updated”) { exit 0 } 否則 { exit 1 } } # 確保輸出資料夾存在 如果 (-not (測試路徑$OutputPath) ) { 試試看 { New-Item -ItemType Directory -Path $OutputPath -Force |Out-Null } 抓 { Write-Warning 「無法建立輸出資料夾:$OutputPath - $_」 } } # 存檔給HOSTNAME_latest.json $outputFile = Join-Path $OutputPath「$ ($hostname) _latest.json」 試試看 { $jsonOutput |Out-File -FilePath $outputFile -編碼 UTF8 -Force Write-Host 「JSON 已儲存至:$outputFile」-ForegroundColor Green } 抓 { Write-Warning 「無法寫入檔案:$outputFile - $_」 # 退回標準 Write-Output $jsonOutput } } 否則 { # 原始行為 - 輸出至標準 Write-Output $jsonOutput }
# 退出代碼:「更新」是根據戰術手冊的成功數值 如果 ($secureBootEnabled -和 $uefica 2023Status -eq 「更新」) { 出口0 # 無問題 } 否則 { 出口1 # 有問題 }