Вихідна дата публікації: 17 листопада 2025 р.
Ідентифікатор KB: 5072718
|
Змінити дату |
Змінити опис |
|
24 лютого 2026 р. |
|
|
22 лютого 2026 р. |
|
|
13 лютого 2026 р. |
|
Зразок сценарію збирання даних реєстру безпечного завантаження
Скопіюйте та вставте цей зразок сценарію та змініть його, якщо потрібно, для середовища: Зразок сценарію збирання даних реєстру безпечного завантаження.
<# . ПІДСУМОК Виявляє стан оновлення сертифіката безпечного завантаження для моніторингу всього флоту.
. ОПИС Цей сценарій виявлення збирає стан безпечного завантаження, значення реєстру оновлення сертифіката, та відомості про пристрій. Він виводить рядок JSON для моніторингу та звітування.
Сумісний з Intune виправленнями, колекцією на основі GPO та іншими інструментами керування.Сценарій виправлення не потрібен – це лише моніторинг.
Exit 0 = "Without issue" (сертифікати оновлено) Exit 1 = "With issue" (сертифікати не оновлюються — лише інформаційні)
. Parameter OutputPath Необов'язково. Шлях до папки, у якій буде збережено JSON-файл.Якщо вказано, HOSTNAME_latest.json зберігається в цій папці.Якщо цього не вказано, виводить JSON у stdout (початкова поведінка).
. ПРИКЛАД # Вивід у stdout (виявлення 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
ПРОГРАМНЕ ЗАБЕЗПЕЧЕННЯ НАДАЄТЬСЯ "ЯК Є", БЕЗ БУДЬ-ЯКИХ ГАРАНТІЙ, ПРЯМИХ АБО НЕЯВНЕ, В ТОМУ ЧИСЛІ, АЛЕ НЕ ОБМЕЖУЄТЬСЯ ГАРАНТІЯМИ ПРИДАТНОСТІ ДО ПРОДАЖУ, ФІТНЕС ДЛЯ ПЕВНОЇ МЕТИ І НЕІНФРИНГУВАННЯ. У ЖОДНОМУ РАЗІ НЕ ЗОБОВ'ЯЗУЄТЬСЯ АВТОРИ АБО ВЛАСНИКИ АВТОРСЬКИХ ПРАВ НЕСУТЬ ВІДПОВІДАЛЬНІСТЬ ЗА БУДЬ-ЯКІ ПРЕТЕНЗІЇ, ЗБИТКИ АБО ІНШІ ВІДПОВІДАЛЬНОСТІ, НЕЗАЛЕЖНО ВІД ТОГО, ЧИ Є ДІЯ КОНТРАКТУ, ЦИВІЛЬНОГО ПРАВОПОРУШЕННЯ АБО ІНШИМ ЧИНОМ, ЩО ВИНИКАЄ ЧЕРЕЗ, НЕ ПОВ'ЯЗАНІ З ПРОГРАМНИМ ЗАБЕЗПЕЧЕННЯМ АБО ВИКОРИСТАННЯМ ЧИ ІНШИМИ СПРАВАМИ В ПРОГРАМНЕ ЗАБЕЗПЕЧЕННЯ.#> param( [Parameter(Mandatory = $false)] [string]$OutputPath )
# URL-адреса завантаження: https://aka.ms/getsecureboot -> "Зразки розгортання та моніторингу" # Примітка. Цей сценарій виконується в кінцевих точках для збирання даних про стан безпечного завантаження.
# 1. Ім'я хоста # ВЕРСІЯ PS: Всі | Admin: Ні | Вимоги до системи: немає спробуйте { $hostname = $env:ІМ'Я КОМП'ЮТЕРА якщо ([рядок]::IsNullOrEmpty($hostname)) { Write-Warning "Не вдалося визначити ім'я хоста" $hostname = "Невідомо" } (}) Write-Host "Ім'я хоста: $hostname" } зловити { Write-Warning "Помилка отримання імені хоста: $_" $hostname = "Помилка" Write-Host "Ім'я хоста: $hostname" }
# 2. Час збирання # ВЕРСІЯ PS: Всі | Admin: Ні | Вимоги до системи: немає спробуйте { $collectionTime = Get-Date якщо ($null -eq $collectionTime) { Write-Warning "Не вдалося отримати поточну дату й час" $collectionTime = "Невідомо" } (}) Write-Host "Час збирання: $collectionTime" } зловити { Write-Warning "Помилка отримання дати й часу: $_" $collectionTime = "Помилка" Write-Host "Час збирання: $collectionTime" }
# Реєстр: головний ключ безпечного завантаження (3 значення)
# 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. Доступні оновлення # ВЕРСІЯ 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) # ВЕРСІЯ 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: Розділ обслуговування (3 значення)
# 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 значень: 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. МікропрограмаVersion # ВЕРСІЯ 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. Дата залишку мікропрограми # ВЕРСІЯ 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 "Може спробувати оновити після: недоступний" }
# Журнали подій: системний журнал (10 значень: 16-25)
# 16-25. Запити журналу подій # Ідентифікатори подій: # 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)
якщо ($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 – витяг з події 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 – витяг з події 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 – видобути KI_<номер> з SkipReason у тій самій події, що й 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. Подія1801Count $event 1801Array = @($events | Where-Object {$_. Id -eq 1801}) $event 1801Count = $event 1801Array.Count Write-Host "Кількість подій 1801: $event 1801Count"
# 20. Кількість подій 1808 $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 (5 значень)
# 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. Час останнього завантаження # ВЕРСІЯ 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. Основна дошкаКерування # ВЕРСІЯ 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. Базовий продукт # ВЕРСІЯ 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 (F33E0C8E002 – оновлення сертифіката безпечного завантаження) # ВЕРСІЯ 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 }
# ============================================================================= # Виявлення виправлення – код виходу стану & виходу # =============================================================================
# Об'єкт стану збірки з усіх зібраних даних про запаси $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 тощо. }
# Вивести стан – для агрегації даних $jsonOutput = $status | ConvertTo-Json –стиснути
# Якщо outputPath надано, збережіть у файл; в іншому разі вивід у 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 }
# Код виходу: "Оновлено" – це значення успіху для плану відтворення if ($secureBootEnabled -and $uefica 2023Status -eq "Оновлено") { вихід 0 # без проблем } інакше { вихід 1 # з проблемою }