Скопіюйте та вставте цей зразок сценарію та змініть його за потреби для свого середовища:

<# . ПІДСУМОК     Виявляє стан оновлення сертифіката безпечного завантаження для моніторингу всього флоту.

.DESCRIPTION     Цей сценарій виявлення збирає стан безпечного завантаження, значення реєстру оновлення сертифіката,     та відомості про пристрій. Він виводить рядок JSON для моніторингу та звітування.

    Compatible with Intune Remediations, GPO-based collection, and other management tools. Сценарій виправлення не потрібен – це лише моніторинг.

    Exit 0 = "Without issue"  (certificates updated)     Exit 1 = "With issue" (сертифікати не оновлюються — лише інформаційні)

.PARAMETER OutputPath     Необов'язково. Шлях до папки, у якій буде збережено JSON-файл.Якщо вказано, HOSTNAME_latest.json зберігається в цій папці.Якщо цього не вказано, виводить JSON у stdout (початкова поведінка).

.EXAMPLE     # Вивід у stdout (виявлення Intune/SCCM)     .\Detect-SecureBootCertUpdateStatus.ps1

.EXAMPLE     # Збереження в мережевій папці (розгортання GPO)     .\Detect-SecureBootCertUpdateStatus.ps1 -OutputPath "\\server\SecureBootLogs$"

.NOTES     Шляхи реєстру на https://aka.ms/securebootplaybook:       HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot       HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     НЕЯВНЕ, В ТОМУ ЧИСЛІ, АЛЕ НЕ ОБМЕЖУЄТЬСЯ ГАРАНТІЯМИ ПРИДАТНОСТІ ДО ПРОДАЖУ,     ФІТНЕС ДЛЯ ПЕВНОЇ МЕТИ І НЕІНФРИНГУВАННЯ. У ЖОДНОМУ РАЗІ НЕ ЗОБОВ'ЯЗУЄТЬСЯ     АВТОРИ АБО ВЛАСНИКИ АВТОРСЬКИХ ПРАВ НЕСУТЬ ВІДПОВІДАЛЬНІСТЬ ЗА БУДЬ-ЯКІ ПРЕТЕНЗІЇ, ЗБИТКИ АБО ІНШІ     ВІДПОВІДАЛЬНОСТІ, НЕЗАЛЕЖНО ВІД ТОГО, ЧИ Є ДІЯ КОНТРАКТУ, ЦИВІЛЬНОГО ПРАВОПОРУШЕННЯ АБО ІНШИМ ЧИНОМ, ЩО ВИНИКАЄ ЧЕРЕЗ,     НЕ ПОВ'ЯЗАНІ З ПРОГРАМНИМ ЗАБЕЗПЕЧЕННЯМ АБО ВИКОРИСТАННЯМ ЧИ ІНШИМИ СПРАВАМИ В     ПРОГРАМНЕ ЗАБЕЗПЕЧЕННЯ.#> param(     [Parameter(Mandatory = $false)]     [string]$OutputPath )

# Download URL: https://aka.ms/getsecureboot -> "Deployment and Monitoring Samples" # Примітка. Цей сценарій виконується в кінцевих точках для збирання даних про стан безпечного завантаження.

# 1. HostName # ВЕРСІЯ PS: Всі | Admin: Ні | Вимоги до системи: немає спробуйте {     $hostname = $env:ІМ'Я КОМП'ЮТЕРА     якщо ([рядок]::IsNullOrEmpty($hostname)) {         Write-Warning "Не вдалося визначити ім'я хоста"         $hostname = "Невідомо"     } (})     Write-Host "Ім'я хоста: $hostname" } зловити {     Write-Warning "Помилка отримання імені хоста: $_"     $hostname = "Помилка"     Write-Host "Ім'я хоста: $hostname" }

# 2. CollectionTime # ВЕРСІЯ PS: Всі | Admin: Ні | Вимоги до системи: немає спробуйте {     $collectionTime = Get-Date     якщо ($null -eq $collectionTime) {         Write-Warning "Не вдалося отримати поточну дату й час"         $collectionTime = "Невідомо"     } (})     Write-Host "Час збирання: $collectionTime" } зловити {     Write-Warning "Помилка отримання дати й часу: $_"     $collectionTime = "Помилка"     Write-Host "Час збирання: $collectionTime" }

# Registry: Secure Boot Main Key (3 values)

# 3. SecureBootEnabled # ВЕРСІЯ PS: 3.0+ | Admin: може знадобитися | Системні вимоги: система з підтримкою UEFI/безпечного завантаження спробуйте {     $secureBootEnabled = Confirm-SecureBootUEFI -ErrorAction Stop     Write-Host "Безпечне завантаження ввімкнуто: $secureBootEnabled" } зловити {     Write-Warning "Не вдалося визначити стан безпечного завантаження за допомогою командлета: $_"     # Спробуйте резервний реєстр     спробуйте {         $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State" -Name UEFISecureBootEnabled -ErrorAction Stop         $secureBootEnabled = [bool]$regValue.UEFISecureBootEnabled         Write-Host "Безпечне завантаження ввімкнуто: $secureBootEnabled"     } зловити {         Write-Warning "Не вдалося визначити стан безпечного завантаження за допомогою реєстру. Система може не підтримувати UEFI/безпечне завантаження."         $secureBootEnabled = $null         Write-Host "Безпечне завантаження ввімкнуто: недоступно"     } (}) }

# 4. HighConfidenceOptOut # ВЕРСІЯ PS: Всі | Admin: може знадобитися | Вимоги до системи: немає спробуйте {     $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name HighConfidenceOptOut -ErrorAction Stop     $highConfidenceOptOut = $regValue.HighConfidenceOptOut     Write-Host "Висока впевненість відмовитися: $highConfidenceOptOut" } зловити {     # HighConfidenceOptOut необов'язковий – відсутній у більшості систем     $highConfidenceOptOut = $null     Write-Host "Висока впевненість відмовитися: не встановлено" }

# 4b. MicrosoftUpdateManagedOptIn # ВЕРСІЯ PS: Всі | Admin: може знадобитися | Вимоги до системи: немає спробуйте {     $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name MicrosoftUpdateManagedOptIn -ErrorAction Stop     $microsoftUpdateManagedOptIn = $regValue.MicrosoftUpdateManagedOptIn     Write-Host "Microsoft Update Managed Opt in: $microsoftUpdateManagedOptIn" } зловити {     # MicrosoftUpdateManagedOptIn необов'язковий – відсутній у більшості систем     $microsoftUpdateManagedOptIn = $null     Write-Host "Microsoft Update Managed Opt in: Not Set" }

# 5. AvailableUpdates # ВЕРСІЯ PS: Всі | Admin: може знадобитися | Вимоги до системи: немає спробуйте {     $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdates -ErrorAction Stop     $availableUpdates = $regValue.AvailableUpdates     якщо ($null -ne $availableUpdates) {         # Перетворити на шістнадцятковий формат         $availableUpdatesHex = "0x{0:X}" -f $availableUpdates         Write-Host "Доступні Оновлення: $availableUpdatesHex"     } інакше {         Write-Host "Доступний Оновлення: недоступно"     } (}) } зловити {     Write-Warning "Розділ реєстру AvailableUpdates не знайдено або недоступний"     $availableUpdates = $null     Write-Host "Доступний Оновлення: недоступний" }

# 5b. AvailableUpdatesPolicy (GPO-controlled persistent value) # ВЕРСІЯ PS: Всі | Admin: може знадобитися | Вимоги до системи: немає спробуйте {     $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdatesPolicy -ErrorAction Stop     $availableUpdatesPolicy = $regValue.AvailableUpdatesPolicy     якщо ($null -ne $availableUpdatesPolicy) {         # Перетворити на шістнадцятковий формат         $availableUpdatesPolicyHex = "0x{0:X}" -f $availableUpdatesPolicy         Write-Host "Доступна політика Оновлення: $availableUpdatesPolicyHex"     } інакше {         Write-Host "Доступна політика Оновлення: не встановлено"     } (}) } зловити {     # AvailableUpdatesPolicy необов'язковий – установлюється лише в разі застосування GPO     $availableUpdatesPolicy = $null     Write-Host "Доступна політика Оновлення: не встановлено" }

# Registry: Servicing Key (3 values)

# 6. UEFICA2023Status # ВЕРСІЯ PS: Всі | Admin: може знадобитися | Вимоги до системи: немає спробуйте {     $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Status -ErrorAction Stop     $uefica 2023Status = $regValue.UEFICA2023Status     Write-Host "Стан Windows UEFI CA 2023: $uefica 2023Status" } зловити {     Write-Warning "Windows UEFI CA 2023 Status registry key not found or inaccessible"     $uefica 2023Status = $null     Write-Host "Стан Windows UEFI CA 2023: недоступний" }

# 7. UEFICA2023Error # ВЕРСІЯ PS: Всі | Admin: може знадобитися | Вимоги до системи: немає спробуйте {     $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Error -ErrorAction Stop     $uefica 2023Error = $regValue.UEFICA2023Error     Write-Host "Помилка UEFI CA 2023: $uefica 2023Помилка" } зловити {     # UEFICA2023Error існує, тільки якщо сталася помилка - відсутність хороша     $uefica 2023Помилка = $null     Write-Host "Помилка UEFI CA 2023: немає" }

# 8. UEFICA2023ErrorEvent # ВЕРСІЯ PS: Всі | Admin: може знадобитися | Вимоги до системи: немає спробуйте {     $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023ErrorEvent -ErrorAction Stop     $uefica 2023ErrorEvent = $regValue.UEFICA2023ErrorEvent     Write-Host "Подія помилки UEFI CA 2023: $uefica 2023ErrorEvent" } зловити {     $uefica 2023ErrorEvent = $null     Write-Host "Подія помилки UEFI CA 2023: недоступно" }

# Registry: Device Attributes (7 values: 9-15)

# 9. OEMManufacturerName # ВЕРСІЯ PS: Всі | Admin: може знадобитися | Вимоги до системи: немає спробуйте {     $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMManufacturerName -ErrorAction Stop     $oemManufacturerName = $regValue.OEMManufacturerName     якщо ([рядок]::IsNullOrEmpty($oemManufacturerName)) {         Write-Warning "OEMManufacturerName пусте"         $oemManufacturerName = "Невідомо"     } (})     Write-Host "Назва виробника оригінального обладнання: $oemManufacturerName" } зловити {     Write-Warning "Розділ реєстру OEMManufacturerName не знайдено або недоступний"     $oemManufacturerName = $null     Write-Host "Назва виробника оригінального обладнання: недоступний" }

# 10. OEMModelSystemFamily # ВЕРСІЯ PS: Всі | Admin: може знадобитися | Вимоги до системи: немає спробуйте {     $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMModelSystemFamily -ErrorAction Stop     $oemModelSystemFamily = $regValue.OEMModelSystemFamily     якщо ([рядок]::IsNullOrEmpty($oemModelSystemFamily)) {         Write-Warning "OEMModelSystemFamily пустий"         $oemModelSystemFamily = "Невідомо"     } (})     Write-Host "Сімейство системи моделі OEM: $oemModelSystemFamily" } зловити {     Write-Warning "Розділ реєстру OEMModelSystemFamily не знайдено або недоступний"     $oemModelSystemFamily = $null     Write-Host "Сімейство системи моделі OEM: недоступно" }

# 11. OEMModelNumber # ВЕРСІЯ PS: Всі | Admin: може знадобитися | Вимоги до системи: немає спробуйте {     $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMModelNumber -ErrorAction Stop     $oemModelNumber = $regValue.OEMModelNumber     якщо ([рядок]::IsNullOrEmpty($oemModelNumber)) {         Write-Warning "OEMModelNumber пустий"         $oemModelNumber = "Невідомо"     } (})     Write-Host "Номер моделі OEM: $oemModelNumber" } зловити {     Write-Warning "Розділ реєстру OEMModelNumber не знайдено або недоступний"     $oemModelNumber = $null     Write-Host "Номер моделі OEM: недоступно" }

# 12. FirmwareVersion # ВЕРСІЯ PS: Всі | Admin: може знадобитися | Вимоги до системи: немає спробуйте {     $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name FirmwareVersion -ErrorAction Stop     $firmwareVersion = $regValue.FirmwareVersion     якщо ([рядок]::IsNullOrEmpty($firmwareVersion)) {         Write-Warning "FirmwareVersion пустий"         $firmwareVersion = "Невідомо"     } (})     Write-Host "Версія мікропрограми: $firmwareVersion" } зловити {     Write-Warning "Розділ реєстру FirmwareVersion не знайдено або недоступний"     $firmwareVersion = $null     Write-Host "Версія мікропрограми: недоступна" }

# 13. FirmwareReleaseDate # ВЕРСІЯ PS: Всі | Admin: може знадобитися | Вимоги до системи: немає спробуйте {     $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name FirmwareReleaseDate -ErrorAction Stop     $firmwareReleaseDate = $regValue.FirmwareReleaseDate     якщо ([рядок]::IsNullOrEmpty($firmwareReleaseDate)) {         Write-Warning "FirmwareReleaseDate пустий"         $firmwareReleaseDate = "Невідомо"     } (})     Write-Host "Дата випуску мікропрограми: $firmwareReleaseDate" } зловити {     Write-Warning "Розділ реєстру FirmwareReleaseDate не знайдено або недоступний"     $firmwareReleaseDate = $null     Write-Host "Дата випуску мікропрограми: недоступний" }

# 14. OSArchitecture # ВЕРСІЯ PS: Всі | Admin: Ні | Вимоги до системи: немає спробуйте {     $osArchitecture = $env:PROCESSOR_ARCHITECTURE     якщо ([рядок]::IsNullOrEmpty($osArchitecture)) {         # Спробуйте резервний реєстр         $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OSArchitecture -ErrorAction Stop         $osArchitecture = $regValue.OSArchitecture     } (})     якщо ([рядок]::IsNullOrEmpty($osArchitecture)) {         Write-Warning "Не вдалося визначити параметр OSArchitecture"         $osArchitecture = "Невідомо"     } (})     Write-Host "Архітектура ОС: $osArchitecture" } зловити {     Write-Warning "Помилка отриманняархівації ОС: $_"     $osArchitecture = "Невідомо"     Write-Host "Архітектура ОС: $osArchitecture" }

# 15. CanAttemptUpdateAfter (FILETIME) # ВЕРСІЯ PS: Всі | Admin: може знадобитися | Вимоги до системи: немає спробуйте {     $regValue = Get-ItemProperty -шлях "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name CanAttemptUpdateAfter -ErrorAction Stop     $canAttemptUpdateAfter = $regValue.CanAttemptUpdateAfter     # Перетворити FILETIME на UTC DateTime – реєстр зберігається як REG_BINARY (байт[]) або REG_QWORD (довгий)     якщо ($null -ne $canAttemptUpdateAfter) {         спробуйте {             якщо ($canAttemptUpdateAfter -це [байт[]]) {                 $fileTime = [BitConverter]::ToInt64($canAttemptUpdateAfter, 0)                 $canAttemptUpdateAfter = [Дата й час]::FromFileTime($fileTime). ToUniversalTime()             } elseif ($canAttemptUpdateAfter -is [long]) {                 $canAttemptUpdateAfter = [DateTime]::FromFileTime($canAttemptUpdateAfter). ToUniversalTime()             } (})         } зловити {             Write-Warning "Не вдалося перетворити CanAttemptUpdateAfter FILETIME на DateTime"         } (})     } (})     Write-Host "Може спробувати оновити після: $canAttemptUpdateAfter" } зловити {     Write-Warning "CanAttemptUpdateAfter registry key not found or inaccessible" (Розділ реєстру CanAttemptUpdateAfter не знайдено або недоступний)     $canAttemptUpdateAfter = $null     Write-Host "Може спробувати оновити після: недоступний" }

# Event Logs: System Log (10 values: 16-25)

# 16-25. Event Log queries # Ідентифікатори подій: # 1801 - ініційовано оновлення, потрібне перезавантаження # 1808 – оновлення успішно завершено # 1795 - мікропрограма повернула помилку (код помилки записування) # 1796 – помилка в журналі з кодом помилки (код записування) # 1800 – потрібне перезавантаження (НЕ помилка – оновлення буде продовжуватися після перезавантаження) # 1802 - Відома проблема мікропрограми заблоковано оновлення (запис KI_<номер> з SkipReason) # 1803 - Відповідне оновлення KEK не знайдено (OEM має постачати ПК підписаний KEK) # ВЕРСІЯ PS: 3.0+ | Admin: може знадобитися для системного журналу | Вимоги до системи: немає спробуйте {     # Запитувати всі відповідні ідентифікатори подій безпечного завантаження     $allEventIds = @(1795, 1796, 1800, 1801, 1802, 1803, 1808)     $events = @(Get-WinEvent -FilterHashtable @{LogName='System'; ID=$allEventIds} - MaxEvents 50 -ErrorAction Stop)

    if ($events.Count -eq 0) {         Write-Warning "У системному журналі не знайдено подій безпечного завантаження"         $latestEventId = $null         $bucketId = $null         $confidence = $null         $skipReasonKnownIssue = $null         $event 1801Count = 0         $event 1808Count = 0         $event 1795Count = 0         $event 1795КодerrorCode = $null         $event 1796Count = 0         $event 1796КодerrorCode = $null         $event 1800Count = 0         $rebootPending = $false         $event 1802Count = 0         $knownIssueId = $null         $event 1803Count = 0         $missingKEK = $false         Write-Host "Найновіший ідентифікатор події: недоступно"         Write-Host "Код сегмента: недоступний"         Write-Host "Впевненість: недоступно"         Write-Host "Подія 1801 Count: 0"         Write-Host "Подія 1808 Count: 0"     } інакше {         # 16. LatestEventId (Найновіший ідентифікатор)         $latestEvent = $events | Sort-Object час, створений за спаданням | Select-Object –перший 1         якщо ($null -eq $latestEvent) {             Write-Warning "Не вдалося визначити останню подію"             $latestEventId = $null             Write-Host "Найновіший ідентифікатор події: недоступно"         } інакше {             $latestEventId = $latestEvent.Id             Write-Host "Найновіший ідентифікатор події: $latestEventId"         }

        # 17. BucketID - Extracted from Event 1801/1808 якщо ($null -ne $latestEvent -and $null -ne $latestEvent.Message) {             якщо ($latestEvent.Message -match 'BucketId:\s*(.+)') {                 $bucketId = $matches[1]. Trim()                 Write-Host "Код сегмента: $bucketId"             } інакше {                 Write-Warning "Код bucketId не знайдено в повідомленні про подію"                 $bucketId = $null                 Write-Host "Код сегмента: не знайдено у події"             } (})         } інакше {             Write-Warning "Остання подія або повідомлення має null-значення, не вдалося видобути BucketId"             $bucketId = $null             Write-Host "Код сегмента: недоступний"         }

        # 18. Confidence - Extracted from Event 1801/1808 якщо ($null -ne $latestEvent -and $null -ne $latestEvent.Message) {             якщо ($latestEvent.Message -match 'BucketConfidenceLevel:\s*(.+)') {                 $confidence = $matches[1]. Trim()                 Write-Host "Впевненість: $confidence"             } інакше {                 Write-Warning "У повідомленні про подію не знайдено довірчий рівень"                 $confidence = $null                 Write-Host "Впевненість: не знайдено у події"             } (})         } інакше {             Write-Warning "Остання подія або повідомлення має null-значення, не вдалося видобути довіру"             $confidence = $null             Write-Host "Впевненість: недоступно"         }

        # 18b. SkipReason - Extract KI_<number> from SkipReason in the same event as BucketId # Це записує відомі ідентифікатори проблем, які відображаються поряд із BucketId/Confidence (не тільки подія 1802)         $skipReasonKnownIssue = $null         якщо ($null -ne $latestEvent -and $null -ne $latestEvent.Message) {             якщо ($latestEvent.Message -match 'SkipReason:\s*(KI_\d+)') {                 $skipReasonKnownIssue = $matches[1]                 Write-Host "Відома проблема SkipReason: $skipReasonKnownIssue" -ForegroundColor Yellow             } (})         }

        # 19. Event1801Count $event 1801Array = @($events | Where-Object {$_. Id -eq 1801})         $event 1801Count = $event 1801Array.Count         Write-Host "Кількість подій 1801: $event 1801Count"

        # 20. Event1808Count $event 1808Array = @($events | Where-Object {$_. Id -eq 1808})         $event 1808Count = $event 1808Array.Count         Write-Host "Кількість подій 1808: $event 1808Count"                  # Ініціалізація змінних подій помилки         $event 1795Count = 0         $event 1795КодerrorCode = $null         $event 1796Count = 0         $event 1796КодerrorCode = $null         $event 1800Count = 0         $rebootPending = $false         $event 1802Count = 0         $knownIssueId = $null         $event 1803Count = 0         $missingKEK = $false                  # Перевірте наявність подій помилок, лише якщо оновлення не завершено         # Пропустити аналіз помилок, якщо: 1808 є останньою подією OR UEFICA2023Status є "Оновлено"         $updateComplete = ($latestEventId -eq 1808) - або ($uefica 2023Status -eq "Оновлено")                  якщо (-не $updateComplete) {             Write-Host "Оновлення не завершено – перевірка наявності подій помилок..." -ForegroundColor Yellow                          # 21. Подія1795 – помилка мікропрограми (код помилки записування)             $event 1795Array = @($events | Where-Object {$_. Id -eq 1795})             $event 1795Count = $event 1795Array.Count             якщо ($event 1795Count -gt 0) {                 $latestEvent 1795 = $event 1795Array | Sort-Object часстворито –за спаданням | Select-Object –перший 1                 якщо ($latestEvent 1795.Повідомлення -match '(?:error|code|status)[:\s]*(?:0x)?( [0-9A-Fa-f]{8}|[0-9A-Fa-f]+)') {                     $event 1795ErrorCode = $matches[1]                 } (})                 Write-Host "Подія 1795 (помилка мікропрограми) Count: $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 1796Array | Sort-Object часстворито –за спаданням | Select-Object –перший 1                 якщо ($latestEvent 1796.Повідомлення -match '(?:error|code|status)[:\s]*(?:0x)?( [0-9A-Fa-f]{8}|[0-9A-Fa-f]+)') {                     $event 1796КодerrorCode = $matches[1]                 } (})                 Write-Host "Event 1796 (Error Logged) Count: $event 1796Count" $(if ($event 1796ErrorCode) { "Код: $event 1796ErrorCode" })             } (})                          # 23. Event1800 – потрібне перезавантаження (НЕ помилка – оновлення буде продовжуватися після перезавантаження)             $event 1800Array = @($events | Where-Object {$_. Id -eq 1800})             $event 1800Count = $event 1800Array.Count             $rebootPending = $event 1800Count -gt 0             якщо ($rebootPending) {                 Write-Host "Подія 1800 (очікування перезавантаження): оновлення буде продовжуватися після перезавантаження" -ForegroundColor Cyan             } (})                          # 24. Подія1802 – відома проблема мікропрограми (запис KI_<номер> з SkipReason)             $event 1802Array = @($events | Where-Object {$_. Id -eq 1802})             $event 1802Count = $event 1802Array.Count             якщо ($event 1802Count -gt 0) {                 $latestEvent 1802 = $event 1802Array | Sort-Object часстворито –за спаданням | Select-Object –перший 1                 якщо ($latestEvent 1802.Message –match 'SkipReason:\s*(KI_\d+)') {                     $knownIssueId = $matches[1]                 } (})                 Write-Host "Подія 1802 (відома проблема з мікропрограмою):$event 1802Count" $(якщо ($knownIssueId) { "KI: $knownIssueId" })             } (})                          # 25. Event1803 – відсутнє оновлення KEK (OEM має надати KEK із підписом PK)             $event 1803Array = @($events | Where-Object {$_. Id -eq 1803})             $event 1803Count = $event 1803Array.Count             $missingKEK = $event 1803Count -gt 0             якщо ($missingKEK) {                 Write-Host "Подія 1803 (відсутній KEK): OEM має поставити ПК підписаний KEK" -ForegroundColor Yellow             } (})         } інакше {             Write-Host "Оновлення завершено (подія 1808 або стан=Оновлено) – пропуск аналізу помилок" -ForegroundColor Green         } (})     } (}) } зловити {     Write-Warning "Помилка отримання журналів подій. Може вимагати права адміністратора: $_"     $latestEventId = $null     $bucketId = $null     $confidence = $null     $skipReasonKnownIssue = $null     $event 1801Count = 0     $event 1808Count = 0     $event 1795Count = 0     $event 1795КодerrorCode = $null     $event 1796Count = 0     $event 1796КодerrorCode = $null     $event 1800Count = 0     $rebootPending = $false     $event 1802Count = 0     $knownIssueId = $null     $event 1803Count = 0     $missingKEK = $false     Write-Host "Найновіший ідентифікатор події: помилка"     Write-Host "Код сегмента: помилка"     Write-Host "Впевненість: помилка"     Write-Host "Подія 1801 Count: 0"     Write-Host "Подія 1808 Count: 0" }

# WMI/CIM Queries (5 values)

# 26. OSVersion # ВЕРСІЯ PS: 3.0+ (використовуйте Get-WmiObject для 2.0) | Admin: Ні | Вимоги до системи: немає спробуйте {     $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop     якщо ($null -eq $osInfo -або [рядок]::IsNullOrEmpty($osInfo.Version)) {         Write-Warning "Не вдалося отримати версію ОС"         $osVersion = "Невідомо"     } інакше {         $osVersion = $osInfo.Version     } (})     Write-Host "Версія ОС: $osVersion" } зловити {     # CIM може не вдатися в деяких середовищах - використовувати резервний варіант     $osVersion = [System.Environment]::OSVersion.Version.ToString()     якщо ([рядок]::IsNullOrEmpty($osVersion)) { $osVersion = "Невідомо" }     Write-Host "Версія ОС: $osVersion" }

# 27. LastBootTime # ВЕРСІЯ PS: 3.0+ (використовуйте Get-WmiObject для 2.0) | Admin: Ні | Вимоги до системи: немає спробуйте {     $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop     якщо ($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 SilentlyContinue). Час початку     } зловити {         $lastBootTime = $null     } (})     якщо ($lastBootTime) { Write-Host "Час останнього завантаження: $lastBootTime" } інакше { Write-Host "Час останнього завантаження: недоступно" } }

# 28. BaseBoardManufacturer # ВЕРСІЯ PS: 3.0+ (використовуйте Get-WmiObject для 2.0) | Admin: Ні | Вимоги до системи: немає спробуйте {     $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop     якщо ($null -eq $baseBoard -або [рядок]::IsNullOrEmpty($baseBoard.Manufacturer)) {         Write-Warning "Не вдалося отримати виробника базової плати"         $baseBoardManufacturer = "Невідомо"     } інакше {         $baseBoardManufacturer = $baseBoard.Manufacturer     } (})     Write-Host "Виробник базової плати: $baseBoardManufacturer" } зловити {     # CIM може не вдаватись – відомості про базову плату додаткові     $baseBoardManufacturer = "Невідомо"     Write-Host "Виробник базової плати: $baseBoardManufacturer" }

# 29. BaseBoardProduct # ВЕРСІЯ PS: 3.0+ (використовуйте Get-WmiObject для 2.0) | Admin: Ні | Вимоги до системи: немає спробуйте {     $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop     якщо ($null -eq $baseBoard -або [рядок]::IsNullOrEmpty($baseBoard.Product)) {         Write-Warning "Не вдалося отримати базовий продукт"         $baseBoardProduct = "Невідомо"     } інакше {         $baseBoardProduct = $baseBoard.Product     } (})     Write-Host "Базовий продукт: $baseBoardProduct" } зловити {     # CIM може не вдаватись – відомості про базову плату додаткові     $baseBoardProduct = "Невідомо"     Write-Host "Базовий продукт: $baseBoardProduct" }

# 30. SecureBootTaskEnabled # ВЕРСІЯ PS: Всі | Admin: Ні | Системні вимоги: заплановане завдання існує # Перевіряє, чи ввімкнуто заплановане завдання secure-Boot-Update $secureBootTaskEnabled = $null $secureBootTaskStatus = "Невідомо" спробуйте {     $taskOutput = schtasks.exe /Query /TN "\Microsoft\Windows\PI\Secure-Boot-Update" /FO CSV 2>&1     якщо ($LASTEXITCODE -eq 0) {         $taskData = $taskOutput | Перетворення файлу CSV         якщо ($taskData) {             $secureBootTaskStatus = $taskData.Стан             $secureBootTaskEnabled = ($taskData.Status - eq "Ready" -or $taskData.Status -eq "Running")         } (})     } інакше {         $secureBootTaskStatus = "NotFound"         $secureBootTaskEnabled = $false     } (})     якщо ($secureBootTaskEnabled -eq $false) {         Write-Host "Завдання оновлення захищеного завантаження: $secureBootTaskStatus (увімкнуто: $secureBootTaskEnabled)" -ForegroundColor Yellow     } інакше {         Write-Host "Завдання оновлення захищеного завантаження: $secureBootTaskStatus (увімкнуто: $secureBootTaskEnabled)" -ForegroundColor Green     } (}) } зловити {     $secureBootTaskStatus = "Помилка"     $secureBootTaskEnabled = $false     Write-Host "Завдання оновлення secureBoot: перевірка помилок – $_" –червоний колір переднього плану }

# 31. WinCS Key Status (F33E0C8E002 - Secure Boot Certificate Update) # ВЕРСІЯ PS: Всі | Admin: Так (для запиту) | Вимоги до системи: WinCsFlags.exe $wincsKeyApplied = $null $wincsKeyStatus = "Невідомо" спробуйте {     # Перевірка поширених розташувань для WinCsFlags.exe     $wincsFlagsPath = $null     $possiblePaths = @(         "$env:SystemRoot\System32\WinCsFlags.exe",         "$env:SystemRoot\SysWOW64\WinCsFlags.exe"     )     foreach ($p in $possiblePaths) {         if ($p test-path) { $wincsFlagsPath = $p; break }     } (})     якщо ($wincsFlagsPath) {         # Певний ключ запиту – потрібні права адміністратора         $queryOutput = & $wincsFlagsPath /query --key F33E0C8E002 2>&1         $queryOutputStr = $queryOutput -join "'n"         якщо ($LASTEXITCODE -eq 0) {             # Перевірте, чи застосовано ключ (знайдіть "Активна конфігурація" або схожий індикатор)             якщо ($queryOutputStr -match "Активна конфігурація.*:.*enabled" -або $queryOutputStr -match "Configuration.*applied") {                 $wincsKeyApplied = $true                 $wincsKeyStatus = "Застосовано"                 Write-Host "WinCS Key F33E0C8E002: Applied" -ForegroundColor Green             } elseif ($queryOutputStr -match "не знайдено|Без конфігурації") {                 $wincsKeyApplied = $false                 $wincsKeyStatus = "NotApplied"                 Write-Host "Ключ WinCS F33E0C8E002: Не застосовується" -ForegroundColor Yellow             } інакше {                 # Ключ існує - перевірка результатів для стану                 $wincsKeyApplied = $true                 $wincsKeyStatus = "Застосовано"                 Write-Host "WinCS Key F33E0C8E002: Applied" -ForegroundColor Green             } (})         } інакше {             # Перевірте наявність конкретних повідомлень про помилки             якщо ($queryOutputStr -match "Немає доступу|адміністратор") {                 $wincsKeyStatus = "AccessDenied"                 Write-Host "F33E0C8E002 ключа WinCS: немає доступу (запуск із правами адміністратора)" -ForegroundColor DarkGray             } elseif ($queryOutputStr -match "не знайдено|Без конфігурації") {                 $wincsKeyApplied = $false                 $wincsKeyStatus = "NotApplied"                 Write-Host "F33E0C8E002 ключа WinCS: Not Applied" -ForegroundColor Yellow             } інакше {                 $wincsKeyStatus = "Запит скасовано"                 Write-Host "F33E0C8E002 ключа WinCS: запит не виконано" -ForegroundColor Red             } (})         } (})     } інакше {         $wincsKeyStatus = "WinCsFlagsNotFound"         Write-Host "F33E0C8E002 ключа WinCS: WinCsFlags.exe не знайдено" -ForegroundColor Gray     } (}) } зловити {     $wincsKeyStatus = "Помилка"     Write-Host "F33E0C8E002 ключа WinCS: перевірка помилок - $_" -ForegroundColor Red }              

# ============================================================================= # Виявлення виправлення – код виходу стану & виходу # =============================================================================

# Build status object from all collected inventory data $status = [ordered]@{     UEFICA2023Status = $uefica 2023Status     UEFICA2023Error = $uefica 2023Error     UEFICA2023ErrorEvent = $uefica 2023ErrorEvent     AvailableUpdates = if ($null -ne $availableUpdates) { $availableUpdatesHex } інакше { $null }     AvailableUpdatesPolicy = if ($null -ne $availableUpdatesPolicy) { $availableUpdatesPolicyHex } інакше { $null }     Hostname = $hostname     CollectionTime = if ($collectionTime -is [datetime]) { $collectionTime.ToString("o") } інакше { "$collectionTime" }     SecureBootEnabled = $secureBootEnabled     HighConfidenceOptOut = $highConfidenceOptOut     MicrosoftUpdateManagedOptIn = $microsoftUpdateManagedOptIn     OEMManufacturerName = $oemManufacturerName     OEMModelSystemFamily = $oemModelSystemFamily     OEMModelNumber = $oemModelNumber     FirmwareVersion = $firmwareVersion     FirmwareReleaseDate = $firmwareReleaseDate     OsArchitecture = $osArchitecture     CanAttemptUpdateAfter = if ($canAttemptUpdateAfter -is [datetime]) { $canAttemptUpdateAfter.ToString("o") } інакше { "$canAttemptUpdateAfter" }     LatestEventId = $latestEventId     Код сегмента = $bucketId     Confidence = $confidence     SkipReasonKnownIssue = $skipReasonKnownIssue # KI_<номер> з події SkipReason in BucketId     Event1801Count = $event 1801Count     Event1808Count = $event 1808Count     # Події помилок із записаними відомостями     Event1795Count = $event 1795Count # мікропрограма повернула помилку     Event1795ErrorCode = $event 1795ErrorCode # Код помилки з мікропрограми     Event1796Count = $event 1796Count # код помилки записано     Event1796ErrorCode = $event 1796ErrorCode # Записаний код помилки     Event1800Count = $event 1800Count # Потрібне перезавантаження (НЕ помилка)     Триває перезавантаження = $rebootPending # True, якщо подія 1800 присутня     Event1802Count = $event 1802Count # Відома проблема з мікропрограмою     KnownIssueId = $knownIssueId # KI_<номер> з SkipReason     Event1803Count = $event 1803Count # Відсутнє оновлення KEK     MissingKEK = $missingKEK # OEM needs to supply PK signed KEK     OSVersion = $osVersion     LastBootTime = if ($lastBootTime -is [datetime]) { $lastBootTime.ToString("o") } інакше { "$lastBootTime" }     BaseBoardManufacturer = $baseBoardManufacturer     BaseBoardProduct = $baseBoardProduct     SecureBootTaskEnabled = $secureBootTaskEnabled     Стан SecureBootTaskStatus = $secureBootTaskStatus     WinCSKeyApplied = $wincsKeyApplied # True, якщо застосовується клавіша F33E0C8E002     WinCSKeyStatus = $wincsKeyStatus # Applied, NotApplied, WinCsFlagsNotFound тощо. }

# Output the status - For data aggregation $jsonOutput = $status | ConvertTo-Json –стиснути

# If OutputPath provided, save to file; otherwise output to stdout якщо (-not [рядок]::IsNullOrEmpty($OutputPath)) {     # Перевірка OutputPath – пропустіть, чи є запит на довідку або містить неприпустимі символи     якщо ($OutputPath -match '^[/\-]' -або $OutputPath -match '[<>:"|? *]') {         Write-Host "Вказано неприпустимий вихідний шлях, виводиться в stdout" -ForegroundColor Yellow         Write-Output $jsonOutput         якщо ($secureBootEnabled -and $uefica 2023Status -eq "Оновлено") { exit 0 } else { exit 1 }     } (})     # Переконайтеся, що папка виводу існує     if (-not (test-path $OutputPath)) {         спробуйте {             New-Item -ItemType Directory – шлях $OutputPath -Force | Out-Null         } зловити {             Write-Warning "Не вдалося створити папку виводу: $OutputPath - $_"         } (})     } (})     # Зберегти в HOSTNAME_latest.json     $outputFile = Join-Path $OutputPath "$($hostname)_latest.json"     спробуйте {         $jsonOutput | Out-File -FilePath $outputFile -Encoding UTF8 -Force         Write-Host "JSON збережено в: $outputFile" -ForegroundColor Green     } зловити {         Write-Warning "Не вдалося записати до файлу: $outputFile - $_"         # Повернутися до stdout         Write-Output $jsonOutput     } (}) } інакше {     # Початкова поведінка – вивід у stdout     Write-Output $jsonOutput }          

# Exit code: "Updated" is the success value per the playbook if ($secureBootEnabled -and $uefica 2023Status -eq "Оновлено") {     вихід 0 # без проблем } інакше {     вихід 1 # з проблемою }

​​​​​​​

Потрібна додаткова довідка?

Потрібні додаткові параметри?

Ознайомтеся з перевагами передплати, перегляньте навчальні курси, дізнайтесь, як захистити свій пристрій тощо.