Oryginalna data publikacji: 17 listopada 2025 r.
Identyfikator BAZY WIEDZY: 5072718
|
Zmień datę |
Zmień opis |
|
24 lutego 2026 r. |
|
|
22 lutego 2026 r. |
|
|
13 lutego 2026 r. |
|
Przykładowy skrypt zbierania danych bezpiecznego rozruchu
Skopiuj i wklej ten przykładowy skrypt i modyfikuj go zgodnie z potrzebami środowiska: skrypt zbierania danych przykładowego bezpiecznego rozruchu.
<# . STRESZCZENIE Wykrywa stan aktualizacji certyfikatu bezpiecznego rozruchu na potrzeby monitorowania całej floty.
. OPIS Ten skrypt wykrywania zbiera stan bezpiecznego rozruchu, wartości rejestru aktualizacji certyfikatu, i informacje o urządzeniu. Powoduje ona utworzenie ciągu JSON w celu monitorowania i raportowania.
Zgodny z rozwiązaniami Intune, kolekcjami opartymi na obiektach GPO i innymi narzędziami do zarządzania.Skrypty naprawcze nie są potrzebne — jest to tylko monitorowanie.
Zakończenie 0 = "Bez problemu" (zaktualizowano certyfikaty) Zakończenie 1 = "Z problemem" (certyfikaty nie zostały zaktualizowane — tylko informacyjne)
. PARAMETER OutputPath Opcjonalne. Ścieżka do folderu, w którym zostanie zapisany plik JSON.Jeśli zostanie udostępniona, HOSTNAME_latest.json zostanie zapisana w tym folderze.Jeśli nie podano, wyjście JSON do stdout (zachowanie oryginalne).
. PRZYKŁAD # Wyjście do stdout (wykrywanie Intune/SCCM) .\Detect-SecureBootCertUpdateStatus.ps1
. PRZYKŁAD # Zapisz w udziale sieciowym (wdrożenie obiektu zasad grupy) .\Detect-SecureBootCertUpdateStatus.ps1 -OutputPath "\\server\SecureBootLogs$"
. NOTATKI Ścieżki rejestru na https://aka.ms/securebootplaybook: HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing
OPROGRAMOWANIE JEST DOSTARCZANE "W TAKIEJ POSTACI, W JAKIEJ JEST", BEZ JAKICHKOLWIEK GWARANCJI, DOROZUMIANE, W TYM MIĘDZY INNYMI GWARANCJE PRZYDATNOŚCI HANDLOWEJ, PRZYDATNOŚĆ DO OKREŚLONEGO CELU I BEZ NARUSZENIA. W ŻADNYM WYPADKU NIE AUTORZY LUB POSIADACZE PRAW AUTORSKICH PONOSZĄ ODPOWIEDZIALNOŚĆ ZA JAKIEKOLWIEK ROSZCZENIA, SZKODY LUB INNE ODPOWIEDZIALNOŚĆ, CZY TO W AKCJI NA RZECZ UMOWY, CZYNU NIEDOZWOLONEGO LUB W INNY SPOSÓB, LUB W ZWIĄZKU Z OPROGRAMOWANIEM, UŻYWANIEM LUB INNYMI TRANSAKCJAMI W OPROGRAMOWANIA.#> param( [Parameter(Mandatory = $false)] [ciąg]$OutputPath )
# Pobierz adres URL: https://aka.ms/getsecureboot -> "Przykłady wdrażania i monitorowania" # Uwaga: Ten skrypt działa w punktach końcowych w celu zbierania danych o stanie bezpiecznego rozruchu.
# 1. Nazwa hosta # Wersja PS: Wszystkie | Administracja: Nie | Wymagania systemowe: Brak wypróbuj { $hostname = $env:COMPUTERNAME if ([ciąg]:IsNullOrEmpty($hostname)) { Write-Warning "Nie można ustalić nazwy hosta" $hostname = "Nieznany" } Write-Host "Hostname: $hostname" } złapać { Write-Warning "Błąd podczas pobierania nazwy hosta: $_" $hostname = "Błąd" Write-Host "Hostname: $hostname" (Nazwa hosta: $hostname) }
# 2. CollectionTime # Wersja PS: Wszystkie | Administracja: Nie | Wymagania systemowe: Brak wypróbuj { $collectionTime = Data uzyskania if ($null -eq $collectionTime) { Write-Warning "Nie można pobrać bieżącej daty/godziny" $collectionTime = "Nieznany" } Write-Host "Czas zbierania danych: $collectionTime" } złapać { Write-Warning "Błąd podczas pobierania daty/godziny: $_" $collectionTime = "Błąd" Write-Host "Czas zbierania danych: $collectionTime" }
# Rejestr: Klucz główny bezpiecznego rozruchu (3 wartości)
# 3. SecureBootEnabled # PS Wersja: 3.0 + | Administracja: Może być wymagane | Wymagania systemowe: system z obsługą interfejsu UEFI/bezpiecznego rozruchu wypróbuj { $secureBootEnabled = Confirm-SecureBootUEFI -ErrorAction Stop Write-Host "Włączony bezpieczny rozruch: $secureBootEnabled" } złapać { Write-Warning "Nie można ustalić stanu bezpiecznego rozruchu za pomocą polecenia cmdlet: $_" # Wypróbuj rezerwowe dane rejestru wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State" -Name UEFISecureBootEnabled -ErrorAction Stop $secureBootEnabled = [bool]$regValue.UEFISecureBootEnabled Write-Host "Włączony bezpieczny rozruch: $secureBootEnabled" } złapać { Write-Warning "Nie można ustalić stanu bezpiecznego rozruchu za pośrednictwem rejestru. System może nie obsługiwać interfejsu UEFI/bezpiecznego rozruchu". $secureBootEnabled = $null Write-Host "Włączony bezpieczny rozruch: niedostępny" } }
# 4. HighConfidenceOptOut # Wersja PS: Wszystkie | Administracja: Może być wymagane | Wymagania systemowe: Brak wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name HighConfidenceOptOut -ErrorAction Stop $highConfidenceOptOut = $regValue.HighConfidenceOptOut Write-Host "High Confidence Opt Out: $highConfidenceOptOut" } złapać { # HighConfidenceOptOut jest opcjonalne — nie występuje w większości systemów $highConfidenceOptOut = $null Write-Host "High Confidence Opt Out: Not Set" (Rezygnacja z dużej pewności siebie: nie ustawiono) }
# 4b. MicrosoftUpdateManagedOptIn # Wersja PS: Wszystkie | Administracja: Może być wymagane | Wymagania systemowe: Brak wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name MicrosoftUpdateManagedOptIn -ErrorAction Stop $microsoftUpdateManagedOptIn = $regValue.MicrosoftUpdateManagedOptIn Write-Host "Microsoft Update Managed Opt In: $microsoftUpdateManagedOptIn" } złapać { # MicrosoftUpdateManagedOptIn jest opcjonalny — nie występuje w większości systemów $microsoftUpdateManagedOptIn = $null Write-Host "Microsoft Update Managed Opt In: Not Set" }
# 5. DostępneUpdates # Wersja PS: Wszystkie | Administracja: Może być wymagane | Wymagania systemowe: Brak wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdates -ErrorAction Stop $availableUpdates = $regValue.AvailableUpdates if ($null -ne $availableUpdates) { # Konwertuj na format szesnastkowo $availableUpdatesHex = "0x{0:X}" -f $availableUpdates Write-Host "Dostępne Aktualizacje: $availableUpdatesHex" } inaczej { Write-Host "Dostępne Aktualizacje: niedostępne" } } złapać { Write-Warning "AvailableUpdates registry key not found or inaccessible" $availableUpdates = $null Write-Host "Dostępne Aktualizacje: niedostępne" }
# 5b. AvailableUpdatesPolicy (trwała wartość kontrolowana przez obiekt zasad grupy) # Wersja PS: Wszystkie | Administracja: Może być wymagane | Wymagania systemowe: Brak wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdatesPolicy -ErrorAction Stop $availableUpdatesPolicy = $regValue.AvailableUpdatesPolicy if ($null -ne $availableUpdatesPolicy) { # Konwertuj na format szesnastkowo $availableUpdatesPolicyHex = "0x{0:X}" -f $availableUpdatesPolicy Write-Host "Dostępne zasady Aktualizacje: $availableUpdatesPolicyHex" } inaczej { Write-Host "Dostępne zasady Aktualizacje: nie ustawiono" } } złapać { # AvailableUpdatesPolicy jest opcjonalne — ustawienie tylko po zastosowaniu obiektu zasad grupy $availableUpdatesPolicy = $null Write-Host "Dostępne zasady Aktualizacje: nie ustawiono" }
# Rejestr: Klucz obsługi (3 wartości)
# 6. UEFICA2023Status # Wersja PS: Wszystkie | Administracja: Może być wymagane | Wymagania systemowe: Brak wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Status -ErrorAction Stop $uefica 2023Status = $regValue.UEFICA2023Status Write-Host "Stan systemu Windows UEFI CA 2023: $uefica 2023Status" } złapać { Write-Warning "Klucz rejestru stanu systemu Windows UEFI CA 2023 nie został znaleziony lub niedostępny" $uefica 2023Status = $null Write-Host "Windows UEFI CA 2023 Status: Niedostępne" }
# 7. UEFICA2023Error # Wersja PS: Wszystkie | Administracja: Może być wymagane | Wymagania systemowe: Brak wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Error -ErrorAction Stop $uefica 2023Error = $regValue.UEFICA2023Error Write-Host "Błąd UEFI CA 2023: $uefica 2023Error" } złapać { # UEFICA2023Error istnieje tylko wtedy, gdy wystąpił błąd — brak jest dobry $uefica 2023Error = $null Write-Host "Błąd UEFI CA 2023: Brak" }
# 8. UEFICA2023ErrorEvent # Wersja PS: Wszystkie | Administracja: Może być wymagane | Wymagania systemowe: Brak wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023ErrorEvent -ErrorAction Stop $uefica 2023ErrorEvent = $regValue.UEFICA2023ErrorEvent Write-Host "Zdarzenie błędu UEFI CA 2023: $uefica 2023ErrorEvent" } złapać { $uefica 2023ErrorEvent = $null Write-Host "Zdarzenie błędu UEFI CA 2023: niedostępne" }
# Rejestr: Atrybuty urządzenia (7 wartości: 9-15)
# 9. OEMManufacturerName # Wersja PS: Wszystkie | Administracja: Może być wymagane | Wymagania systemowe: Brak wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMManufacturerName -ErrorAction Stop $oemManufacturerName = $regValue.OEMManufacturerName if ([ciąg]:IsNullOrEmpty($oemManufacturerName)) { Write-Warning "Nazwa OEMManufacturerName jest pusta" $oemManufacturerName = "Nieznany" } Write-Host "Nazwa producenta OEM: $oemManufacturerName" } złapać { Write-Warning "Klucz rejestru OEMManufacturerName nie został znaleziony lub niedostępny" $oemManufacturerName = $null Write-Host "Nazwa producenta OEM: niedostępne" }
# 10. OEMModelSystemFamily # Wersja PS: Wszystkie | Administracja: Może być wymagane | Wymagania systemowe: Brak wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMModelSystemFamily -ErrorAction Stop $oemModelSystemFamily = $regValue.OEMModelSystemFamily if ([string]::IsNullOrEmpty($oemModelSystemFamily)) { Write-Warning "OEMModelSystemFamily is empty" $oemModelSystemFamily = "Nieznany" } Write-Host "Rodzina systemów OEM: $oemModelSystemFamily" } złapać { Write-Warning "Klucz rejestru OEMModelSystemFamily nie został znaleziony lub niedostępny" $oemModelSystemFamily = $null Write-Host "Rodzina systemów modeli OEM: niedostępne" }
# 11. OEMModelNumber # Wersja PS: Wszystkie | Administracja: Może być wymagane | Wymagania systemowe: Brak wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMModelNumber -ErrorAction Stop $oemModelNumber = $regValue.OEMModelNumber if ([ciąg]:IsNullOrEmpty($oemModelNumber)) { Write-Warning "OEMModelNumber jest pusty" $oemModelNumber = "Nieznany" } Write-Host "Numer modelu OEM: $oemModelNumber" } złapać { Write-Warning "Klucz rejestru OEMModelNumber nie został znaleziony lub niedostępny" $oemModelNumber = $null Write-Host "Numer modelu OEM: niedostępny" }
# 12. FirmwareVersion # Wersja PS: Wszystkie | Administracja: Może być wymagane | Wymagania systemowe: Brak wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name FirmwareVersion -ErrorAction Stop $firmwareVersion = $regValue.FirmwareVersion if ([ciąg]:IsNullOrEmpty($firmwareVersion)) { Write-Warning "FirmwareVersion is empty" (Wersja oprogramowania układowego jest pusta) $firmwareVersion = "Nieznany" } Write-Host "Wersja oprogramowania układowego: $firmwareVersion" } złapać { Write-Warning "Klucz rejestru firmwareVersion nie został znaleziony lub niedostępny" $firmwareVersion = $null Write-Host "Wersja oprogramowania układowego: niedostępna" }
# 13. FirmwareReleaseDate # Wersja PS: Wszystkie | Administracja: Może być wymagane | Wymagania systemowe: Brak wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name FirmwareReleaseDate -ErrorAction Stop $firmwareReleaseDate = $regValue.FirmwareReleaseDate if ([string]::IsNullOrEmpty($firmwareReleaseDate)) { Write-Warning "FirmwareReleaseDate is empty" $firmwareReleaseDate = "Nieznany" } Write-Host "Data wydania oprogramowania układowego: $firmwareReleaseDate" } złapać { Write-Warning "FirmwareReleaseDate registry key not found or inaccessible" $firmwareReleaseDate = $null Write-Host "Data wydania oprogramowania układowego: niedostępne" }
# 14. OSArchitecture # Wersja PS: Wszystkie | Administracja: Nie | Wymagania systemowe: Brak wypróbuj { $osArchitecture = $env:PROCESSOR_ARCHITECTURE if ([ciąg]:IsNullOrEmpty($osArchitecture)) { # Wypróbuj rezerwowe dane rejestru $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OSArchitecture -ErrorAction Stop $osArchitecture = $regValue.OSArchitecture } if ([ciąg]:IsNullOrEmpty($osArchitecture)) { Write-Warning "Nie można ustalić OSArchitecture" $osArchitecture = "Nieznany" } Write-Host "Architektura systemu operacyjnego: $osArchitecture" } złapać { Write-Warning "Error retrieving OSArchitecture: $_" $osArchitecture = "Nieznany" Write-Host "Architektura systemu operacyjnego: $osArchitecture" }
# 15. CanAttemptUpdateAfter (FILETIME) # Wersja PS: Wszystkie | Administracja: Może być wymagane | Wymagania systemowe: Brak wypróbuj { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name CanAttemptUpdateAfter -ErrorAction Stop $canAttemptUpdateAfter = $regValue.CanAttemptUpdateAfter # Convert FILETIME to UTC DateTime — registry stores as REG_BINARY (byte[]) or REG_QWORD (long) if ($null -ne $canAttemptUpdateAfter) { wypróbuj { if ($canAttemptUpdateAfter -is [bajt[]]) { $fileTime = [BitConverter]::ToInt64($canAttemptUpdateAfter; 0) $canAttemptUpdateAfter = [DateTime]::FromFileTime($fileTime). ToUniversalTime() } elseif ($canAttemptUpdateAfter -is [long]) { $canAttemptUpdateAfter = [DateTime]::FromFileTime($canAttemptUpdateAfter). ToUniversalTime() } } złapać { Write-Warning "Could not convert CanAttemptUpdateAfter FILETIME to DateTime" } } Write-Host "Może próbować zaktualizować po: $canAttemptUpdateAfter" } złapać { Write-Warning "CanAttemptUpdateAfter registry key not found or inaccessible" $canAttemptUpdateAfter = $null Write-Host "Może próbować zaktualizować po: niedostępne" }
# Dzienniki zdarzeń: Dziennik systemowy (10 wartości: 16-25)
# 16-25. Zapytania dziennika zdarzeń # Identyfikatory zdarzeń: # 1801 — Aktualizacja zainicjowana, wymagane ponowne uruchomienie # 1808 — Pomyślnie ukończono aktualizację # 1795 — Zwrócono błąd oprogramowania układowego (kod błędu przechwytywania) # 1796 — Błąd zarejestrowany z kodem błędu (kod przechwytywania) # 1800 - Wymagane ponowne uruchomienie (NIE błąd - aktualizacja będzie kontynuowana po ponownym uruchomieniu) # 1802 — Znany problem z oprogramowaniem układowym zablokował aktualizację (przechwytywanie KI_<numeru> z SkipReason) # 1803 - Pasujące aktualizacji KEK nie znaleziono (OEM musi dostarczyć PK podpisane KEK) # PS Wersja: 3.0 + | Administracja: Może być wymagane w dzienniku systemowym | Wymagania systemowe: Brak wypróbuj { # Prześlij zapytanie o wszystkie odpowiednie identyfikatory zdarzeń bezpiecznego rozruchu $allEventIds = @(1795, 1796, 1800, 1801, 1802, 1803, 1808) $events = @(Get-WinEvent -FilterHashtable @{LogName='System'; ID=$allEventIds} -MaxEvents 50 -ErrorAction Stop)
jeżeli ($events. Liczba -eq 0) { Write-Warning "Brak zdarzeń bezpiecznego rozruchu znalezionych w dzienniku systemu" $latestEventId = $null $bucketId = $null $confidence = $null $skipReasonKnownIssue = $null $event 1801Count = 0 $event 1808Count = 0 $event 1795Count = 0 $event 1795ErrorCode = $null $event 1796Count = 0 $event 1796ErrorCode = $null $event 1800Count = 0 $rebootPending = $false $event 1802Count = 0 $knownIssueId = $null $event 1803Count = 0 $missingKEK = $false Write-Host "Najnowszy identyfikator zdarzenia: niedostępne" Write-Host "Identyfikator zasobnika: niedostępny" Write-Host "Pewność siebie: niedostępne" Write-Host "Liczba zdarzeń 1801: 0" Write-Host "Zdarzenie 1808 Liczba: 0" } inaczej { # 16. LatestEventId $latestEvent = $events | Sort-Object TimeCreated -Descending | Select-Object -Pierwsza 1 if ($null -eq $latestEvent) { Write-Warning "Nie można ustalić najnowszego zdarzenia" $latestEventId = $null Write-Host "Najnowszy identyfikator zdarzenia: niedostępne" } inaczej { $latestEventId = $latestEvent.Id Write-Host "Najnowszy identyfikator zdarzenia: $latestEventId" }
# 17. Identyfikator zasobnika — wyodrębnione z zdarzenia 1801/1808 if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) { if ($latestEvent.Message -match 'BucketId:\s*(.+)') { $bucketId = $matches[1]. Trim() Write-Host "Identyfikator zasobnika: $bucketId" } inaczej { Write-Warning "Nie można odnaleźć zasobnika w komunikacie zdarzenia" $bucketId = $null Write-Host "Identyfikator zasobnika: nie można odnaleźć w zdarzeniu" } } inaczej { Write-Warning "Najnowsze zdarzenie lub wiadomość ma wartość null, nie można wyodrębnić identyfikatora zasobnika" $bucketId = $null Write-Host "Identyfikator zasobnika: niedostępne" }
# 18. Pewność siebie — wyodrębniona z wydarzenia 1801/1808 if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) { if ($latestEvent.Message -match 'BucketConfidenceLevel:\s*(.+)') { $confidence = $matches[1]. Trim() Write-Host "Pewność siebie: $confidence" } inaczej { Write-Warning "Poziom ufności nie można odnaleźć w komunikacie zdarzenia" $confidence = $null Write-Host "Pewność siebie: nie znaleziono w zdarzeniu" } } inaczej { Write-Warning "Najnowsze zdarzenie lub wiadomość ma wartość null, nie można wyodrębnić ufności" $confidence = $null Write-Host "Pewność siebie: niedostępne" }
# 18b. SkipReason — wyodrębnianie KI_<numeru> z SkipReason w tym samym zdarzeniu co Identyfikator Zasobnika # Spowoduje to przechwycenie identyfikatorów znanych problemów, które są wyświetlane obok identyfikatora zasobnika/ufności (nie tylko zdarzenia 1802) $skipReasonKnownIssue = $null if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) { if ($latestEvent.Message -match 'SkipReason:\s*(KI_\d+)') { $skipReasonKnownIssue = $matches[1] Write-Host "SkipReason Known Issue: $skipReasonKnownIssue" -ForegroundColor Yellow } }
# 19. Event1801Count $event 1801Array = @($events | Where-Object {$_. Identyfikator -eq 1801}) $event 1801Count = $event 1801Array.Count Write-Host "Event 1801 Count: $event 1801Count"
# 20. Event1808Count $event 1808Array = @($events | Where-Object {$_. Identyfikator -eq 1808}) $event 1808Count = $event 1808Array.Count Write-Host "Event 1808 Count: $event 1808Count" # Inicjowanie zmiennych zdarzeń błędu $event 1795Count = 0 $event 1795ErrorCode = $null $event 1796Count = 0 $event 1796ErrorCode = $null $event 1800Count = 0 $rebootPending = $false $event 1802Count = 0 $knownIssueId = $null $event 1803Count = 0 $missingKEK = $false # Sprawdź tylko występowanie zdarzeń błędów, jeśli aktualizacja NIE została ukończona # Pomiń analizę błędów, jeśli: 1808 jest najnowszym zdarzeniem LUB UEFICA2023Status is "Updated" $updateComplete = ($latestEventId -eq 1808) -lub ($uefica 2023Status -eq "Aktualizacja") jeżeli (nie $updateComplete) { Write-Host "Update not complete - checking for error events..." -ForegroundColor Yellow # 21. Zdarzenie1795 — błąd oprogramowania układowego (kod błędu przechwytywania) $event 1795Array = @($events | Where-Object {$_. Identyfikator —1795}) $event 1795Count = $event 1795Array.Count if ($event 1795Count -gt 0) { $latestEvent 1795 = $event 1795Array | Sort-Object TimeCreated -Descending | Select-Object -Pierwsza 1 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 "Zdarzenie 1795 (błąd oprogramowania układowego) Liczba: $event 1795Count" $(if ($event 1795ErrorCode) { "Kod: $event 1795ErrorCode" }) } # 22. Zdarzenie1796 — Kod błędu Zarejestrowany (kod błędu przechwytywania) $event 1796Array = @($events | Where-Object {$_. Identyfikator -eq 1796}) $event 1796Count = $event 1796Array.Count if ($event 1796Count -gt 0) { $latestEvent 1796 = $event 1796Array | Sort-Object TimeCreated -Descending | Select-Object -Pierwsza 1 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 "Event 1796 (Error Logged) Count: $event 1796Count" $(if ($event 1796ErrorCode) { "Code: $event 1796ErrorCode" }) } # 23. Zdarzenie1800 — wymagane ponowne uruchomienie (NIE jest to błąd — aktualizacja będzie kontynuowana po ponownym uruchomieniu) $event 1800Array = @($events | Where-Object {$_. Identyfikator —1800}) $event 1800Count = $event 1800Array.Count $rebootPending = $event 1800Count -gt 0 if ($rebootPending) { Write-Host "Zdarzenie 1800 (oczekiwanie na ponowne uruchomienie): Aktualizacja będzie kontynuowana po ponownym uruchomieniu" -ForegroundColor Cyan } # 24. Zdarzenie1802 — znany problem z oprogramowaniem układowym (przechwytywanie numeru KI_<> z SkipReason) $event 1802Array = @($events | Where-Object {$_. Identyfikator —eq 1802}) $event 1802Count = $event 1802Array.Count if ($event 1802Count -gt 0) { $latestEvent 1802 = $event 1802Array | Sort-Object TimeCreated -Descending | Select-Object -Pierwsza 1 if ($latestEvent 1802.Message -match 'SkipReason:\s*(KI_\d+)') { $knownIssueId = $matches[1] } Write-Host "Zdarzenie 1802 (znany problem z oprogramowaniem układowym) Liczba: $event 1802Count" $(if ($knownIssueId) { "KI: $knownIssueId" }) } # 25. Zdarzenie1803 - Brak aktualizacji KEK (OEM musi dostarczyć KEK podpisane PK) $event 1803Array = @($events | Where-Object {$_. Identyfikator —1803}) $event 1803Count = $event 1803Array.Count $missingKEK = $event 1803Count -gt 0 if ($missingKEK) { Write-Host "Event 1803 (missing KEK): OEM needs to supply PK signed KEK" -ForegroundColor Yellow } } inaczej { Write-Host "Update complete (Event 1808 or Status=Updated) - skipping error analysis" -ForegroundColor Green } } } złapać { Write-Warning "Błąd podczas pobierania dzienników zdarzeń. Może wymagać uprawnień administratora: $_" $latestEventId = $null $bucketId = $null $confidence = $null $skipReasonKnownIssue = $null $event 1801Count = 0 $event 1808Count = 0 $event 1795Count = 0 $event 1795ErrorCode = $null $event 1796Count = 0 $event 1796ErrorCode = $null $event 1800Count = 0 $rebootPending = $false $event 1802Count = 0 $knownIssueId = $null $event 1803Count = 0 $missingKEK = $false Write-Host "Najnowszy identyfikator zdarzenia: błąd" Write-Host "Identyfikator zasobnika: błąd" Write-Host "Ufność: błąd" Write-Host "Zdarzenie 1801 Liczba: 0" Write-Host "Zdarzenie 1808 Liczba: 0" }
# Zapytania WMI/CIM (5 wartości)
# 26. Osversion # PS Wersja: 3.0 + (użyj Get-WmiObject dla 2.0) | Administracja: Nie | Wymagania systemowe: Brak wypróbuj { $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop if ($null -eq $osInfo -lub [string]::IsNullOrEmpty($osInfo.Version)) { Write-Warning "Nie można pobrać wersji systemu operacyjnego" $osVersion = "Nieznany" } inaczej { $osVersion = $osInfo.Version } Write-Host "Wersja systemu operacyjnego: $osVersion" } złapać { # CIM może zakończyć się niepowodzeniem w niektórych środowiskach — użycie rezerwy $osVersion = [System.Environment]::OSVersion.Version.ToString() if ([string]::IsNullOrEmpty($osVersion)) { $osVersion = "Unknown" } Write-Host "Wersja systemu operacyjnego: $osVersion" }
# 27. LastBootTime # PS Wersja: 3.0 + (użyj Get-WmiObject dla 2.0) | Administracja: Nie | Wymagania systemowe: Brak wypróbuj { $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop if ($null -eq $osInfo -lub $null -eq $osInfo.LastBootUpTime) { Write-Warning "Nie można pobrać ostatniego rozruchu" $lastBootTime = $null Write-Host "Czas ostatniego rozruchu: niedostępny" } inaczej { $lastBootTime = $osInfo.LastBootUpTime Write-Host "Czas ostatniego rozruchu: $lastBootTime" } } złapać { # CIM może zakończyć się niepowodzeniem w niektórych środowiskach — użycie rezerwy wypróbuj { $lastBootTime = (Get-Process -Id 0 -ErrorAction SilentlyContinue). Starttime } złapać { $lastBootTime = $null } if ($lastBootTime) { Write-Host "Last Boot Time: $lastBootTime" } else { Write-Host "Last Boot Time: Not Available" } }
# 28. BaseBoardManufacturer # PS Wersja: 3.0 + (użyj Get-WmiObject dla 2.0) | Administracja: Nie | Wymagania systemowe: Brak wypróbuj { $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop if ($null -eq $baseBoard -lub [string]::IsNullOrEmpty($baseBoard.Manufacturer)) { Write-Warning "Nie można pobrać producenta płyty podstawowej" $baseBoardManufacturer = "Nieznany" } inaczej { $baseBoardManufacturer = $baseBoard.Producent } Write-Host "Baseboard Manufacturer: $baseBoardManufacturer" } złapać { #CIM may fail - baseboard info is supplementary $baseBoardManufacturer = "Nieznany" Write-Host "Baseboard Manufacturer: $baseBoardManufacturer" }
# 29. Produkt BaseBoard # PS Wersja: 3.0 + (użyj Get-WmiObject dla 2.0) | Administracja: Nie | Wymagania systemowe: Brak wypróbuj { $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop if ($null -eq $baseBoard -lub [ciąg]::IsNullOrEmpty($baseBoard.Product)) { Write-Warning "Nie można pobrać produktu baseboard" $baseBoardProduct = "Nieznany" } inaczej { $baseBoardProduct = $baseBoard.Product } Write-Host "Produkt baseboard: $baseBoardProduct" } złapać { #CIM may fail - baseboard info is supplementary $baseBoardProduct = "Nieznany" Write-Host "Produkt baseboard: $baseBoardProduct" }
# 30. SecureBootTaskEnabled # Wersja PS: Wszystkie | Administracja: Nie | Wymagania systemowe: zaplanowane zadanie istnieje # Sprawdza, czy zaplanowane zadanie bezpiecznego rozruchu jest włączone $secureBootTaskEnabled = $null $secureBootTaskStatus = "Nieznany" wypróbuj { $taskOutput = schtasks.exe /Query /TN "\Microsoft\Windows\PI\Secure-Boot-Update" /FO CSV 2>&1 if ($LASTEXITCODE -eq 0) { $taskData = $taskOutput | ConvertFrom-Csv if ($taskData) { $secureBootTaskStatus = $taskData.Status $secureBootTaskEnabled = ($taskData.Status -eq 'Ready' -lub $taskData.Status -eq 'Running') } } inaczej { $secureBootTaskStatus = "NotFound" $secureBootTaskEnabled = $false } if ($secureBootTaskEnabled -eq $false) { Write-Host "SecureBoot Update Task: $secureBootTaskStatus (Enabled: $secureBootTaskEnabled)" -ForegroundColor Yellow } inaczej { Write-Host "SecureBoot Update Task: $secureBootTaskStatus (Enabled: $secureBootTaskEnabled)" -ForegroundColor Green } } złapać { $secureBootTaskStatus = "Błąd" $secureBootTaskEnabled = $false Write-Host "SecureBoot Update Task: Error checking - $_" -ForegroundColor Red }
# 31. Stan klucza WinCS (F33E0C8E002 — aktualizacja certyfikatu bezpiecznego rozruchu) # Wersja PS: Wszystkie | Administracja: Tak (dla zapytania) | Wymagania systemowe: WinCsFlags.exe $wincsKeyApplied = $null $wincsKeyStatus = "Nieznany" wypróbuj { # Sprawdzanie typowych lokalizacji pod kątem WinCsFlags.exe $wincsFlagsPath = $null $possiblePaths = @( "$env:SystemRoot\System32\WinCsFlags.exe", "$env:SystemRoot\SysWOW64\WinCsFlags.exe" ) foreach ($p w $possiblePaths) { if (Test-Path $p) { $wincsFlagsPath = $p; break } } if ($wincsFlagsPath) { # Klucz zapytania — wymaga praw administratora $queryOutput = & $wincsFlagsPath /query --key F33E0C8E002 2>&1 $queryOutputStr = $queryOutput -join "'n" if ($LASTEXITCODE -eq 0) { # Sprawdź, czy klawisz został zastosowany (poszukaj pozycji "Aktywna konfiguracja" lub podobny wskaźnik) if ($queryOutputStr -match "Active Configuration.*:.*enabled" -lub $queryOutputStr -match "Configuration.*applied") { $wincsKeyApplied = $true $wincsKeyStatus = "Zastosowano" Write-Host "WinCS Key F33E0C8E002: Applied" -ForegroundColor Green } elseif ($queryOutputStr -match "nie znaleziono|Brak konfiguracji") { $wincsKeyApplied = $false $wincsKeyStatus = "NotApplied" Write-Host "WinCS Key F33E0C8E002: Not Applied" -ForegroundColor Yellow } inaczej { # Key exists - check output for state $wincsKeyApplied = $true $wincsKeyStatus = "Zastosowano" Write-Host "WinCS Key F33E0C8E002: Applied" -ForegroundColor Green } } inaczej { # Sprawdź, czy nie ma konkretnych komunikatów o błędach if ($queryOutputStr -match "Odmowa dostępu|administrator") { $wincsKeyStatus = "AccessDenied" Write-Host "WinCS Key F33E0C8E002: Access denied (run as admin)" -ForegroundColor DarkGray } elseif ($queryOutputStr -match "nie znaleziono|Brak konfiguracji") { $wincsKeyApplied = $false $wincsKeyStatus = "NotApplied" Write-Host "WinCS Key F33E0C8E002: Not Applied" -ForegroundColor Yellow } inaczej { $wincsKeyStatus = "Zapytanie nie powiodło się" Write-Host "F33E0C8E002 klucza WinCS: zapytanie nie powiodło się" —Kolor pierwszego planu Kolor czerwony } } } inaczej { $wincsKeyStatus = "WinCsFlagsNotFound" Write-Host "WinCS Key F33E0C8E002: WinCsFlags.exe nie można odnaleźć" -ForegroundColor Gray } } złapać { $wincsKeyStatus = "Błąd" Write-Host "WinCS Key F33E0C8E002: Error checking - $_" -ForegroundColor Red }
# ============================================================================= # Wykrywanie korygowania — kod wyjścia stanu & # =============================================================================
# Build status object from all collected inventory data $status = [zamówione]@{ UEFICA2023Status = $uefica 2023Status UEFICA2023Error = $uefica 2023Error UEFICA2023ErrorEvent = $uefica 2023ErrorEvent AvailableUpdates = if ($null -ne $availableUpdates) { $availableUpdatesHex } inaczej { $null } AvailableUpdatesPolicy = if ($null -ne $availableUpdatesPolicy) { $availableUpdatesPolicyHex } inaczej { $null } Hostname = $hostname CollectionTime = if ($collectionTime -is [datetime]) { $collectionTime.ToString("o") } inaczej { "$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") } inaczej { "$canAttemptUpdateAfter" } LatestEventId = $latestEventId BucketId = $bucketId Pewność siebie = $confidence SkipReasonKnownIssue = $skipReasonKnownIssue # KI_<> numeru z skipReason w zdarzeniu BucketId Event1801Count = $event 1801Count Event1808Count = $event 1808Count # Zdarzenia błędów z przechwyconymi szczegółami Zdarzenie1795Count = $event 1795Count # Firmware returned error Zdarzenie1795ErrorCode = $event 1795ErrorCode # Kod błędu z oprogramowania układowego Event1796Count = $event 1796Count #Error code logged Zdarzenie1796ErrorCode = $event 1796ErrorCode # Przechwycony kod błędu Zdarzenie1800Count = $event 1800Count # Wymagane ponowne uruchomienie (NIE jest to błąd) RebootPending = $rebootPending # True if Event 1800 present Event1802Count = $event 1802Count # Znany problem z oprogramowaniem układowym KnownIssueId = $knownIssueId # KI_<> numeru z SkipReason Event1803Count = $event 1803Count # Missing KEK update MissingKEK = $missingKEK # OEM musi dostarczyć KEK podpisane PK OSVersion = $osVersion LastBootTime = if ($lastBootTime -is [datetime]) { $lastBootTime.ToString("o") } inaczej { "$lastBootTime" } BaseBoardManufacturer = $baseBoardManufacturer BaseBoardProduct = $baseBoardProduct SecureBootTaskEnabled = $secureBootTaskEnabled SecureBootTaskStatus = $secureBootTaskStatus WinCSKeyApplied = $wincsKeyApplied # True, jeśli zastosowano klawisz F33E0C8E002 WinCSKeyStatus = $wincsKeyStatus # Applied, NotApplied, WinCsFlagsNotFound itp. }
# Wyprowadź stan — dla agregacji danych $jsonOutput = $status | ConvertTo-Json -Kompresuj
# Jeśli program OutputPath jest podany, zapisz go w pliku; w przeciwnym razie dane wyjściowe do stdout if (-not [string]::IsNullOrEmpty($OutputPath)) { #Validate OutputPath - skip if it looks like a help request or has invalid chars if ($OutputPath -match '^[/\-]' -lub $OutputPath -match '[<>:"|? *]') { Write-Host "Określono nieprawidłowy program OutputPath, wyjście do wydruku" —Kolor pierwszego planu Żółty Write-Output $jsonOutput if ($secureBootEnabled -and $uefica 2023Status -eq "Updated") { exit 0 } inaczej { exit 1 } } # Upewnij się, że folder wyjściowy istnieje if (-not (Test-Path $OutputPath)) { wypróbuj { New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null } złapać { Write-Warning "Nie można utworzyć folderu wyjściowego: $OutputPath - $_" } } # Zapisz w HOSTNAME_latest.json $outputFile = Join-Path $OutputPath "$($hostname)_latest.json" wypróbuj { $jsonOutput | Out-File -FilePath $outputFile -Kodowanie UTF8 -Force Write-Host "JSON saved to: $outputFile" -ForegroundColor Green } złapać { Write-Warning "Nie można pisać do pliku: $outputFile - $_" # Powrót do stdout Write-Output $jsonOutput } } inaczej { # Oryginalne zachowanie — wyjście do stdout Write-Output $jsonOutput }
# Kod wyjścia: "Zaktualizowano" to wartość sukcesu dla każdego podręcznika if ($secureBootEnabled -and $uefica 2023Status -eq "Updated") { exit 0 # Without issue } inaczej { exit 1 # With issue }