Ursprüngliches Veröffentlichungsdatum: 17. November 2025
KB ID: 5072718
|
Datum ändern |
Beschreibung ändern |
|
24. Februar 2026 |
|
|
22. Februar 2026 |
|
|
13. Februar 2026 |
|
Beispielskript zur Sammlung von Secure-Boot-Bestandsdaten
Kopieren Sie dieses Beispielskript, fügen Sie es ein und passen Sie es bei Bedarf an Ihre Umgebung an: Das Beispielskript zur Sammlung von Secure-Boot-Bestandsdaten.
<# .SYNOPSIS Erkennt den Status von Secure-Boot-Zertifikatupdates zur flottenweiten Überwachung.
.BESCHREIBUNG Dieses Erkennungsskript sammelt den Secure-Boot-Status, Registrierungswerte zu Zertifikatupdates, und Geräteinformationen. Es gibt eine JSON-Zeichenfolge zur Überwachung und Berichterstellung aus.
Kompatibel mit Intune-Remediations, GPO-basierter Sammlung und anderen Verwaltungstools. Es wird kein Korrekturskript benötigt – dies dient nur der Überwachung.
Exit 0 = "Without issue" (Zertifikate aktualisiert) Exit 1 = "With issue" (Zertifikate nicht aktualisiert – nur informativ)
.PARAMETER OutputPath Optional. Pfad zu einem Ordner, in dem die JSON-Datei gespeichert wird. Falls angegeben, wird HOSTNAME_latest.json in diesem Ordner gespeichert. Wenn nicht angegeben, wird JSON an stdout ausgegeben (ursprüngliches Verhalten).
. BEISPIEL # Ausgabe in stdout (Intune/SCCM-Erkennung) .\Detect-SecureBootCertUpdateStatus.ps1
. BEISPIEL # In Netzwerkfreigabe speichern (GPO-Bereitstellung) .\Detect-SecureBootCertUpdateStatus.ps1 -OutputPath "\\server\SecureBootLogs$"
.NOTIZEN Registrierungspfade laut https://aka.ms/securebootplaybook: HKLM:\\SYSTEM\\CurrentControlSet\\Control\\SecureBoot HKLM:\\SYSTEM\\CurrentControlSet\\Control\\SecureBoot\\Servicing
DIE SOFTWARE WIRD „WIE BESEHEN“ UND OHNE GARANTIE JEGLICHER ART BEREITGESTELLT, OB AUSDRÜCKLICH ODER STILLSCHWEIGEND, EINSCHLIESSLICH U. A. DEN GARANTIEN DER MARKTGÄNGIGKEIT, EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND NICHTVERLETZUNG GEWERBLICHER SCHUTZRECHTE. IN KEINEM FALL ÜBERNEHMEN DIE AUTOREN ODER URHEBERRECHTSINHABER EINE HAFTUNG FÜR ANSPRÜCHE, SCHÄDEN ODER ANDERE HAFTUNGEN, OB IM RAHMEN EINES VERTRAGS, UNERLAUBTER HANDLUNG ODER ANDERWEITIG, DIE SICH AUS ODER IN VERBINDUNG MIT DER SOFTWARE ODER DER VERWENDUNG ODER ANDEREN AKTIVITÄTEN MIT DER SOFTWARE ERGEBEN. #> param( [Parameter(Mandatory = $false)] [string]$OutputPath )
# Download-URL: https://aka.ms/getsecureboot -> "Beispiele für Bereitstellung und Überwachung" # Hinweis: Dieses Skript wird auf Endpunkten ausgeführt, um Daten zum Secure-Boot-Status zu sammeln.
# 1. HostName # PS Version: Alle | Admin: Nein | Systemanforderungen: Keine try { $hostname = $env:COMPUTERNAME if ([string]::IsNullOrEmpty($hostname)) { Write-Warning "Hostname konnte nicht ermittelt werden" $hostname = "Unbekannt" } Write-Host "Hostname: $hostname" } catch { Write-Warning "Fehler beim Abrufen des Hostnamens: $_" $hostname = "Fehler" Write-Host "Hostname: $hostname" }
# 2. CollectionTime # PS Version: Alle | Admin: Nein | Systemanforderungen: Keine try { $collectionTime = Get-Date if ($null -eq $collectionTime) { Write-Warning "Aktuelles Datum/Uhrzeit konnte nicht abgerufen werden" $collectionTime = "Unbekannt" } Write-Host "Erfassungszeit: $collectionTime" } catch { Write-Warning "Fehler beim Abrufen von Datum/Uhrzeit: $_" $collectionTime = "Fehler" Write-Host "Erfassungszeit: $collectionTime" }
# Registrierung: Secure Boot Main Key (3 Werte)
# 3. SecureBootEnabled # PS Version: 3.0 und höher | Admin: Möglicherweise erforderlich | Systemanforderungen: UEFI/Secure-Boot-fähiges System try { $secureBootEnabled = Confirm-SecureBootUEFI -ErrorAction Stop Write-Host "Secure Boot aktiviert: $secureBootEnabled" } catch { Write-Warning "Secure-Boot-Status konnte nicht über das Cmdlet ermittelt werden: $_" # Versuchen Sie das Fallback über die Registrierung try { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State" -Name UEFISecureBootEnabled -ErrorAction Stop $secureBootEnabled = [bool]$regValue.UEFISecureBootEnabled Write-Host "Secure Boot aktiviert: $secureBootEnabled" } catch { Write-Warning "Secure-Boot-Status konnte nicht über die Registrierung ermittelt werden." Das System unterstützt UEFI/Secure Boot möglicherweise nicht." $secureBootEnabled = $null Write-Host "Secure Boot aktiviert: Nicht verfügbar" } }
# 4. HighConfidenceOptOut # PS Version: Alle | Admin: Möglicherweise erforderlich | Systemanforderungen: Keine try { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name HighConfidenceOptOut -ErrorAction Stop $highConfidenceOptOut = $regValue.HighConfidenceOptOut Write-Host "High Confidence Opt Out: $highConfidenceOptOut" } catch { # HighConfidenceOptOut ist optional – auf den meisten Systemen nicht vorhanden $highConfidenceOptOut = $null Write-Host "High Confidence Opt Out: Nicht festgelegt" }
# 4b. MicrosoftUpdateManagedOptIn # PS Version: Alle | Admin: Möglicherweise erforderlich | Systemanforderungen: Keine try { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name MicrosoftUpdateManagedOptIn -ErrorAction Stop $microsoftUpdateManagedOptIn = $regValue.MicrosoftUpdateManagedOptIn Write-Host "Von Microsoft Update verwaltete Anmeldung: $microsoftUpdateManagedOptIn" } catch { # MicrosoftUpdateManagedOptIn ist optional und auf den meisten Systemen nicht vorhanden. $microsoftUpdateManagedOptIn = $null Write-Host "Von Microsoft Update verwaltete Anmeldung: Nicht festgelegt" }
# 5. AvailableUpdates # PS Version: Alle | Admin: Möglicherweise erforderlich | Systemanforderungen: Keine try { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdates -ErrorAction Stop $availableUpdates = $regValue.AvailableUpdates if ($null -ne $availableUpdates) { # In hexadezimales Format konvertieren $availableUpdatesHex = "0x{0:X}" -f $availableUpdates Write-Host "Verfügbare Updates: $availableUpdatesHex" } else { Write-Host "Verfügbare Updates: Nicht verfügbar" } } catch { Write-Warning "AvailableUpdates-Registrierungsschlüssel nicht gefunden oder nicht zugänglich" $availableUpdates = $null Write-Host "Verfügbare Updates: Nicht verfügbar" }
# 5b. AvailableUpdatesPolicy (vom GPO gesteuerter persistenter Wert) # PS Version: Alle | Admin: Möglicherweise erforderlich | Systemanforderungen: Keine try { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdatesPolicy -ErrorAction Stop $availableUpdatesPolicy = $regValue.AvailableUpdatesPolicy if ($null -ne $availableUpdatesPolicy) { # In hexadezimales Format konvertieren $availableUpdatesPolicyHex = "0x{0:X}" -f $availableUpdatesPolicy Write-Host "Richtlinie für verfügbare Updates: $availableUpdatesPolicyHex" } else { Write-Host "Richtlinie für verfügbare Updates: Nicht festgelegt" } } catch { # AvailableUpdatesPolicy ist optional – nur gesetzt, wenn GPO angewendet wird $availableUpdatesPolicy = $null Write-Host "Richtlinie für verfügbare Updates: Nicht festgelegt" }
# Registrierung: Servicing Key (3 Werte)
# 6. UEFICA2023Status # PS Version: Alle | Admin: Möglicherweise erforderlich | Systemanforderungen: Keine try { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Status -ErrorAction Stop $uefica2023Status = $regValue.UEFICA2023Status Write-Host "Windows UEFI CA 2023 Status: $uefica2023Status" } catch { Write-Warning "Windows UEFI CA 2023 Status-Registrierungsschlüssel nicht gefunden oder nicht zugänglich" $uefica2023Status = $null Write-Host "Windows UEFI CA 2023 Status: Nicht verfügbar" }
# 7. UEFICA2023Fehler # PS Version: Alle | Admin: Möglicherweise erforderlich | Systemanforderungen: Keine try { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Error -ErrorAction Stop $uefica2023Error = $regValue.UEFICA2023Error Write-Host "UEFI CA 2023 Fehler: $uefica2023Error" } catch { # UEFICA2023Error ist nur vorhanden, wenn ein Fehler aufgetreten ist – Abwesenheit ist gut $uefica2023Error = $null Write-Host "UEFI CA 2023 Fehler: Keine" }
# 8. UEFICA2023ErrorEvent # PS-Version: Alle | Administrator: Möglicherweise erforderlich | Systemanforderungen: Keine versuchen{ $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023ErrorEvent -ErrorAction Stop $uefica 2023ErrorEvent = $regValue.UEFICA2023ErrorEvent Write-Host "UEFI CA 2023 Error Event: $uefica 2023ErrorEvent" } catch { $uefica 2023ErrorEvent = $null Schreibhost "UEFI CA 2023-Fehlerereignis: Nicht verfügbar" }
# Registrierung: Geräteattribute (7 Werte: 9-15)
# 9. OEMManufacturerName # PS Version: Alle | Admin: Möglicherweise erforderlich | Systemanforderungen: Keine try { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMManufacturerName -ErrorAction Stop $oemManufacturerName = $regValue.OEMManufacturerName if ([string]::IsNullOrEmpty($oemManufacturerName)) { Write-Warning "OEMManufacturerName ist leer" $oemManufacturerName = "Unbekannt" } Write-Host "OEM-Herstellername: $oemManufacturerName" } catch { Write-Warning "OEMManufacturerName-Registrierungsschlüssel nicht gefunden oder nicht zugänglich" $oemManufacturerName = $null Write-Host "OEM-Herstellername: Nicht verfügbar" }
# 10. OEMModelSystemFamily # PS-Version: Alle | Administrator: Möglicherweise erforderlich | Systemanforderungen: Keine versuchen{ $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMModelSystemFamily -ErrorAction Stop $oemModelSystemFamily = $regValue.OEMModelSystemFamily wenn ([Zeichenfolge]::IsNullOrEmpty($oemModelSystemFamily)) { Schreibwarnung "OEMModelSystemFamily is empty" $oemModelSystemFamily = "Unknown" } Write-Host "OEM Model System Family: $oemModelSystemFamily" } catch { Schreibwarnung "OEMModelSystemFamily-Registrierungsschlüssel nicht gefunden oder nicht zugänglich" $oemModelSystemFamily = $null Schreibhost "OEM-Modellsystemfamilie: Nicht verfügbar" }
# 11. OEMModelNumber # PS-Version: Alle | Administrator: Möglicherweise erforderlich | Systemanforderungen: Keine versuchen{ $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMModelNumber -ErrorAction Stop $oemModelNumber = $regValue.OEMModelNumber wenn ([Zeichenfolge]::IsNullOrEmpty($oemModelNumber)) { Schreibwarnung "OEMModelNumber is empty" $oemModelNumber = "Unknown" } Write-Host "OEM Model Number: $oemModelNumber" } catch { Schreibwarnung "OEMModelNumber-Registrierungsschlüssel nicht gefunden oder nicht zugänglich" $oemModelNumber = $null Schreibhost "OEM-Modellnummer: Nicht verfügbar" }
# 12. FirmwareVersion # PS-Version: Alle | Administrator: Möglicherweise erforderlich | Systemanforderungen: Keine versuchen{ $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name FirmwareVersion -ErrorAction Stop $firmwareVersion = $regValue.FirmwareVersion wenn ([Zeichenfolge]::IsNullOrEmpty($firmwareVersion)) { Schreibwarnung "FirmwareVersion is empty" $firmwareVersion = "Unknown" } Write-Host "Firmwareversion: $firmwareVersion" } catch { Schreibwarnung "FirmwareVersion-Registrierungsschlüssel nicht gefunden oder nicht zugänglich" $firmwareVersion = $null Schreibhost "Firmwareversion: Nicht verfügbar" }
# 13. FirmwareReleaseDate # PS Version: Alle | Admin: Möglicherweise erforderlich | Systemanforderungen: Keine try { $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 ist leer" $firmwareReleaseDate = "Unbekannt" } Write-Host "Firmware-Veröffentlichungsdatum: $firmwareReleaseDate" } catch { Write-Warning "FirmwareReleaseDate-Registrierungsschlüssel nicht gefunden oder nicht zugänglich" $firmwareReleaseDate = $null Write-Host "Firmware-Veröffentlichungsdatum: Nicht verfügbar" }
# 14. OSArchitecture # PS Version: Alle | Admin: Nein | Systemanforderungen: Keine try { $osArchitecture = $env:PROCESSOR_ARCHITECTURE if ([string]::IsNullOrEmpty($osArchitecture)) { # Versuchen Sie das Fallback über die Registrierung $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OSArchitecture -ErrorAction Stop $osArchitecture = $regValue.OSArchitecture } if ([string]::IsNullOrEmpty($osArchitecture)) { Write-Warning "OSArchitecture konnte nicht bestimmt werden" $osArchitecture = "Unbekannt" } Write-Host "Betriebssystemarchitektur: $osArchitecture" } catch { Write-Warning "Fehler beim Abrufen von OSArchitecture: $_" $osArchitecture = "Unbekannt" Write-Host "Betriebssystemarchitektur: $osArchitecture" }
# 15. CanAttemptUpdateAfter (FILETIME) # PS Version: Alle | Admin: Möglicherweise erforderlich | Systemanforderungen: Keine try { $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name CanAttemptUpdateAfter -ErrorAction Stop $canAttemptUpdateAfter = $regValue.CanAttemptUpdateAfter # FILETIME in UTC-Datum und -Uhrzeit konvertieren – im Registrierungswert als REG_BINARY (Byte[]) oder REG_QWORD (long) gespeichert if ($null -ne $canAttemptUpdateAfter) { try { if ($canAttemptUpdateAfter -is [byte[]]) { $fileTime = [BitConverter]::ToInt64($canAttemptUpdateAfter, 0) $canAttemptUpdateAfter = [DateTime]::FromFileTime($fileTime).ToUniversalTime() } elseif ($canAttemptUpdateAfter -is [long]) { $canAttemptUpdateAfter = [DateTime]::FromFileTime($canAttemptUpdateAfter).ToUniversalTime() } } catch { Write-Warning "Kann CanAttemptUpdateAfter FILETIME nicht in DateTime konvertieren" } } Write-Host "Kann Updateversuch nach: $canAttemptUpdateAfter starten" } catch { Write-Warning "CanAttemptUpdateAfter-Registrierungsschlüssel nicht gefunden oder nicht zugänglich" $canAttemptUpdateAfter = $null Write-Host "Kann Updateversuch nach: Nicht verfügbar" }
# Ereignisprotokolle: Systemprotokoll (10 Werte: 16-25)
# 16-25. Ereignisprotokollabfragen # Ereignis-IDs: # 1801 – Update initiiert, Neustart erforderlich # 1808 – Update erfolgreich abgeschlossen # 1795 – Firmwarefehler zurückgegeben (Fehlercode erfassen) # 1796 – Fehler mit Fehlercode protokolliert (Code erfassen) # 1800 – Neustart erforderlich (KEIN Fehler – Update wird nach Neustart fortgesetzt) # 1802 – Bekanntes Firmwareproblem blockierte das Update (KI_<number> aus SkipReason erfassen) # 1803 – Passendes KEK-Update nicht gefunden (OEM muss PK-signiertes KEK bereitstellen) # PS Version: 3.0 und höher | Admin: Für Systemprotokoll möglicherweise erforderlich | Systemanforderungen: Keine try { # Alle relevanten Secure-Boot-Ereignis-IDs abfragen $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 "Im Systemprotokoll wurden keine Secure-Boot-Ereignisse gefunden" $latestEventId = $null $bucketId = $null $confidence = $null $skipReasonKnownIssue = $null $event1801Count = 0 $event1808Count = 0 $event1795Count = 0 $event1795ErrorCode = $null $event1796Count = 0 $event1796ErrorCode = $null $event1800Count = 0 $rebootPending = $false $event1802Count = 0 $knownIssueId = $null $event1803Count = 0 $missingKEK = $false Write-Host "Neueste Ereignis-ID: Nicht verfügbar" Write-Host "Bucket-ID: Nicht verfügbar" Write-Host "Konfidenz: Nicht verfügbar" Write-Host "Ereignis 1801 Count: 0" Write-Host "Ereignis 1808 Count: 0" } else { # 16. LatestEventId $latestEvent = $events | Sort-Object TimeCreated -Descending | Select-Object -First 1 if ($null -eq $latestEvent) { Write-Warning "Das neueste Ereignis konnte nicht ermittelt werden" $latestEventId = $null Write-Host "Neueste Ereignis-ID: Nicht verfügbar" } else { $latestEventId = $latestEvent.Id Write-Host "Neueste Ereignis-ID: $latestEventId" }
# 17. BucketID – Extrahiert aus Ereignis 1801/1808 if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) { if ($latestEvent.Message -match 'BucketId:\s*(.+)') { $bucketId = $matches[1].Trim() Write-Host "Bucket-ID: $bucketId" } else { Write-Warning "BucketId in Ereignismeldung nicht gefunden" $bucketId = $null Write-Host "Bucket-ID: Im Ereignis nicht gefunden" } } else { Write-Warning "Neueste Ereignis oder Nachricht ist NULL, BucketId kann nicht extrahiert werden" $bucketId = $null Write-Host "Bucket-ID: Nicht verfügbar" }
# 18. Konfidenz : Extrahiert aus Ereignis 1801/1808 if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) { if ($latestEvent.Message -match 'BucketConfidenceLevel:\s*(.+)') { $confidence = $matches[1]. Trim() Write-Host "Vertrauen: $confidence" } else { Write-Warning "Konfidenzniveau in Ereignismeldung nicht gefunden" $confidence = $null Write-Host "Confidence: Not Found in Event" } } else { Write-Warning "Latest event or message is NULL, cannot extract Confidence" (Aktuelles Ereignis oder neueste Nachricht ist NULL, kann die Zuverlässigkeit nicht extrahieren) $confidence = $null Write-Host "Konfidenz: Nicht verfügbar" }
# 18b. SkipReason – Extrahieren KI_<number> aus SkipReason im selben Ereignis wie BucketId # Erfasst bekannte Problem-IDs, die zusammen mit BucketId/Konfidenz angezeigt werden (nicht nur Ereignis 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 $event1801Array = @($events | Where-Object {$_.Id -eq 1801}) $event1801Count = $event1801Array.Count Write-Host "Ereignis 1801 Anzahl: $event1801Count"
# 20. Event1808Count $event1808Array = @($events | Where-Object {$_.Id -eq 1808}) $event1808Count = $event1808Array.Count Write-Host "Ereignis 1808 Count: $event1808Count" # Fehlerereignisvariablen initialisieren $event1795Count = 0 $event1795ErrorCode = $null $event1796Count = 0 $event1796ErrorCode = $null $event1800Count = 0 $rebootPending = $false $event1802Count = 0 $knownIssueId = $null $event1803Count = 0 $missingKEK = $false # Nur nach Fehlerereignissen suchen, wenn das Update NICHT abgeschlossen ist # Fehleranalyse überspringen, wenn 1808 das neueste Ereignis ist ODER UEFICA2023Status "Updated" ist $updateComplete = ($latestEventId -eq 1808) -or ($uefica2023Status -eq "Updated") if (-not $updateComplete) { Write-Host "Update nicht abgeschlossen – Überprüfung auf Fehlerereignisse..." -ForegroundColor Yellow # 21. Event1795 – Firmware-Fehler (Fehlercode erfassen) $event1795Array = @($events | Where-Object {$_.Id -eq 1795}) $event1795Count = $event1795Array.Count if ($event1795Count -gt 0) { $latestEvent1795 = $event1795Array | Sort-Object TimeCreated -Descending | Select-Object -First 1 if ($latestEvent1795.Message -match '(?:error|code|status)[:\s]*(?:0x)?([0-9A-Fa-f]{8}|[0-9A-Fa-f]+)') { $event1795ErrorCode = $matches[1] } Write-Host "Event 1795 (Firmware-Fehler) Count: $event1795Count" $(if ($event1795ErrorCode) { "Code: $event1795ErrorCode" }) } # 22. Event1796 – Fehlercode protokolliert (Fehlercode erfassen) $event1796Array = @($events | Where-Object {$_.Id -eq 1796}) $event1796Count = $event1796Array.Count if ($event1796Count -gt 0) { $latestEvent1796 = $event1796Array | Sort-Object TimeCreated -Descending | Select-Object -First 1 if ($latestEvent1796.Message -match '(?:error|code|status)[:\s]*(?:0x)?([0-9A-Fa-f]{8}|[0-9A-Fa-f]+)') { $event1796ErrorCode = $matches[1] } Write-Host "Event 1796 (Fehler protokolliert) Count: $event1796Count" $(if ($event1796ErrorCode) { "Code: $event1796ErrorCode" }) } # 23. Event1800 – Neustart erforderlich (KEIN Fehler – Update wird nach dem Neustart fortgesetzt) $event1800Array = @($events | Where-Object {$_.Id -eq 1800}) $event1800Count = $event1800Array.Count $rebootPending = $event1800Count -gt 0 if ($rebootPending) { Write-Host "Ereignis 1800 (Neustart ausstehend): Update wird nach dem Neustart fortgesetzt" -ForegroundColor Cyan } # 24. Event1802 – Bekanntes Firmwareproblem (Erfassen KI_<number> von SkipReason) $event1802Array = @($events | Where-Object {$_.Id -eq 1802}) $event1802Count = $event1802Array.Count if ($event1802Count -gt 0) { $latestEvent1802 = $event1802Array | Sort-Object TimeCreated -Descending | Select-Object -First 1 if ($latestEvent1802.Message -match 'SkipReason:\s*(KI_\d+)') { $knownIssueId = $matches[1] } Write-Host "Ereignis 1802 (Bekanntes Firmwareproblem) Anzahl: $event1802Count" $(if ($knownIssueId) { "KI: $knownIssueId" }) } # 25. Event1803 – Fehlendes KEK-Update (OEM muss PK-signierten KEK bereitstellen) $event1803Array = @($events | Where-Object {$_.Id -eq 1803}) $event1803Count = $event1803Array.Count $missingKEK = $event1803Count -gt 0 if ($missingKEK) { Write-Host "Ereignis 1803 (Fehlendes KEK): OEM muss PK-signierten KEK bereitstellen" -ForegroundColor Yellow } } else { Write-Host "Update abgeschlossen (Ereignis 1808 oder Status=Aktualisiert) – Fehleranalyse wird übersprungen" -ForegroundColor Green } } } catch { Write-Warning "Fehler beim Abrufen der Ereignisprotokolle." Möglicherweise sind Administratorrechte erforderlich: $_" $latestEventId = $null $bucketId = $null $confidence = $null $skipReasonKnownIssue = $null $event1801Count = 0 $event1808Count = 0 $event1795Count = 0 $event1795ErrorCode = $null $event1796Count = 0 $event1796ErrorCode = $null $event1800Count = 0 $rebootPending = $false $event1802Count = 0 $knownIssueId = $null $event1803Count = 0 $missingKEK = $false Write-Host "Neueste Ereignis-ID: Fehler" Write-Host "Bucket-ID: Fehler" Write-Host "Zuverlässigkeit: Fehler" Write-Host "Ereignis 1801 Anzahl: 0" Write-Host "Ereignis 1808 Anzahl: 0" }
# WMI/CIM-Abfragen (5 Werte)
# 26. OSVersion # PS Version: 3.0 und höher (für 2.0 Get-WmiObject verwenden) | Admin: Nein | Systemanforderungen: Keine try { $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop if ($null -eq $osInfo -or [string]::IsNullOrEmpty($osInfo.Version)) { Write-Warning "Betriebssystemversion konnte nicht abgerufen werden" $osVersion = "Unbekannt" } else { $osVersion = $osInfo.Version } Write-Host "Betriebssystemversion: $osVersion" } catch { # CIM kann in manchen Umgebungen fehlschlagen – Fallback $osVersion = [System.Environment]::OSVersion.Version.ToString() if ([string]::IsNullOrEmpty($osVersion)) { $osVersion = "Unbekannt" } Write-Host "Betriebssystemversion: $osVersion" }
# 27. LastBootTime # PS Version: 3.0 und höher (für 2.0 Get-WmiObject verwenden) | Admin: Nein | Systemanforderungen: Keine try { $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop if ($null -eq $osInfo -or $null -eq $osInfo.LastBootUpTime) { Write-Warning "Zeitpunkt des letzten Starts konnte nicht abgerufen werden" $lastBootTime = $null Write-Host "Zeitpunkt des letzten Starts: Nicht verfügbar" } else { $lastBootTime = $osInfo.LastBootUpTime Write-Host "Zeitpunkt des letzten Starts: $lastBootTime" } } catch { # CIM kann in manchen Umgebungen fehlschlagen – Fallback try { $lastBootTime = (Get-Process -Id 0 -ErrorAction SilentlyContinue).StartTime } catch { $lastBootTime = $null } if ($lastBootTime) { Write-Host "Zeitpunkt des letzten Starts: $lastBootTime" } else { Write-Host "Zeitpunkt des letzten Starts: Nicht verfügbar" } }
# 28. BaseBoardManufacturer # PS Version: 3.0 und höher (für 2.0 Get-WmiObject verwenden) | Admin: Nein | Systemanforderungen: Keine try { $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop if ($null -eq $baseBoard -or [string]::IsNullOrEmpty($baseBoard.Manufacturer)) { Write-Warning "Baseboardhersteller konnte nicht abgerufen werden" $baseBoardManufacturer = "Unbekannt" } else { $baseBoardManufacturer = $baseBoard.Manufacturer } Write-Host "Baseboardhersteller: $baseBoardManufacturer" } catch { # CIM kann fehlschlagen – Baseboard-Informationen sind ergänzend $baseBoardManufacturer = "Unbekannt" Write-Host "Baseboardhersteller: $baseBoardManufacturer" }
# 29. BaseBoardProduct # PS Version: 3.0 und höher (für 2.0 Get-WmiObject verwenden) | Admin: Nein | Systemanforderungen: Keine try { $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop if ($null -eq $baseBoard -or [string]::IsNullOrEmpty($baseBoard.Product)) { Write-Warning "Baseboardprodukt konnte nicht abgerufen werden" $baseBoardProduct = "Unbekannt" } else { $baseBoardProduct = $baseBoard.Product } Write-Host "Baseboardprodukt: $baseBoardProduct" } catch { # CIM kann fehlschlagen – Baseboard-Informationen sind ergänzend $baseBoardProduct = "Unbekannt" Write-Host "Baseboardprodukt: $baseBoardProduct" }
# 30. SecureBootTaskEnabled # PS Version: Alle | Admin: Nein | Systemanforderungen: Geplante Aufgabe vorhanden # Prüft, ob die geplante Aufgabe "Secure-Boot-Update" aktiviert ist $secureBootTaskEnabled = $null $secureBootTaskStatus = "Unbekannt" try { $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' -or $taskData.Status -eq 'Running') } } else { $secureBootTaskStatus = "Nicht gefunden" $secureBootTaskEnabled = $false } if ($secureBootTaskEnabled -eq $false) { Write-Host "SecureBoot Update Task: $secureBootTaskStatus (Aktiviert: $secureBootTaskEnabled)" -ForegroundColor Yellow } else { Write-Host "SecureBoot Update Task: $secureBootTaskStatus (Aktiviert: $secureBootTaskEnabled)" -ForegroundColor Green } } catch { $secureBootTaskStatus = "Fehler" $secureBootTaskEnabled = $false Write-Host "SecureBoot-Updatetask: Fehler bei der Überprüfung – $_" -ForegroundColor Red }
# 31. WinCS-Schlüsselstatus (F33E0C8E002 – Secure Boot-Zertifikataktualisierung) # PS-Version: Alle | Admin: Ja (für Abfrage) | Systemanforderungen: WinCsFlags.exe $wincsKeyApplied = $null $wincsKeyStatus = "Unbekannt" try { # Überprüfe übliche Speicherorte für WinCsFlags.exe $wincsFlagsPath = $null $possiblePaths = @( "$env:SystemRoot\System32\WinCsFlags.exe", "$env:SystemRoot\SysWOW64\WinCsFlags.exe" ) foreach ($p in $possiblePaths) { if (Test-Path $p) {{ $wincsFlagsPath = $p; break }} } if ($wincsFlagsPath) { # Schlüssel abfragen – erfordert Administratorrechte $queryOutput = & $wincsFlagsPath /query --key F33E0C8E002 2>&1 $queryOutputStr = $queryOutput -join "`n" if ($LASTEXITCODE -eq 0) { # Prüfe, ob der Schlüssel angewendet ist (Suche nach "Active Configuration" oder ähnlichem Indikator) if ($queryOutputStr -match "Active Configuration.*:.*enabled" -or $queryOutputStr -match "Configuration.*applied") { $wincsKeyApplied = $true $wincsKeyStatus = "Angewendet" Write-Host "WinCS Key F33E0C8E002: Angewendet" -ForegroundColor Green } elseif ($queryOutputStr -match "not found|No configuration") { $wincsKeyApplied = $false $wincsKeyStatus = "NichtAngewendet" Write-Host "WinCS Key F33E0C8E002: Nicht angewendet" -ForegroundColor Yellow } else { # Schlüssel vorhanden – Ausgabe auf Status prüfen $wincsKeyApplied = $true $wincsKeyStatus = "Angewendet" Write-Host "WinCS Key F33E0C8E002: Angewendet" -ForegroundColor Green } } else { # Prüfe auf spezifische Fehlermeldungen if ($queryOutputStr -match "Access denied|administrator") { $wincsKeyStatus = "ZugriffVerweigert" Write-Host "WinCS Key F33E0C8E002: Zugriff verweigert (als Administrator ausführen)" -ForegroundColor DarkGray } elseif ($queryOutputStr -match "not found|No configuration") { $wincsKeyApplied = $false $wincsKeyStatus = "NichtAngewendet" Write-Host "WinCS Key F33E0C8E002: Nicht angewendet" -ForegroundColor Yellow } else { $wincsKeyStatus = "AbfrageFehlgeschlagen" Write-Host "WinCS Key F33E0C8E002: Abfrage fehlgeschlagen" -ForegroundColor Red } } } else { $wincsKeyStatus = "WinCsFlagsNichtGefunden" Write-Host "WinCS Key F33E0C8E002: WinCsFlags.exe nicht gefunden" -ForegroundColor Gray } } catch { $wincsKeyStatus = "Fehler" Write-Host "WinCS Key F33E0C8E002: Fehler bei der Überprüfung – $_" -ForegroundColor Red }
# ============================================================================= # Erkennung der Wartung – Statusausgabe und Exitcode # =============================================================================
# Statusobjekt aus allen gesammelten Bestandsdaten erstellen $status = [ordered]@{ UEFICA2023Status = $uefica2023Status UEFICA2023Error = $uefica2023Error UEFICA2023ErrorEvent = $uefica2023ErrorEvent AvailableUpdates = if ($null -ne $availableUpdates) { $availableUpdatesHex } else { $null } AvailableUpdatesPolicy = if ($null -ne $availableUpdatesPolicy) { $availableUpdatesPolicyHex } else { $null } Hostname = $hostname CollectionTime = if ($collectionTime -is [datetime]) { $collectionTime.ToString("o") } else { "$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") } else { "$canAttemptUpdateAfter" } LatestEventId = $latestEventId BucketId = $bucketId Confidence = $confidence SkipReasonKnownIssue = $skipReasonKnownIssue # KI_<number> aus SkipReason im BucketId-Ereignis Event1801Count = $event1801Count Event1808Count = $event1808Count # Fehlerereignisse mit erfassten Details Event1795Count = $event1795Count # Firmware hat Fehler zurückgegeben Event1795ErrorCode = $event1795ErrorCode # Fehlercode von Firmware Event1796Count = $event1796Count # Fehlercode protokolliert Event1796ErrorCode = $event1796ErrorCode # Erfasster Fehlercode Event1800Count = $event1800Count # Neustart erforderlich (KEIN Fehler) RebootPending = $rebootPending # True, wenn Ereignis 1800 vorhanden Event1802Count = $event1802Count # Bekanntes Firmwareproblem KnownIssueId = $knownIssueId # KI_<number> aus SkipReason Event1803Count = $event1803Count # Fehlendes KEK-Update MissingKEK = $missingKEK # OEM muss PK-signierten KEK bereitstellen OSVersion = $osVersion LastBootTime = if ($lastBootTime -is [datetime]) { $lastBootTime.ToString("o") } else { "$lastBootTime" } BaseBoardManufacturer = $baseBoardManufacturer BaseBoardProduct = $baseBoardProduct SecureBootTaskEnabled = $secureBootTaskEnabled SecureBootTaskStatus = $secureBootTaskStatus WinCSKeyApplied = $wincsKeyApplied # True, wenn F33E0C8E002-Schlüssel angewendet WinCSKeyStatus = $wincsKeyStatus # Angewendet, Nicht angewendet, WinCsFlagsNichtGefunden usw. }
# Ausgabe des Status – für die Datenaggregation $jsonOutput = $status | ConvertTo-Json -Compress
# Wenn OutputPath angegeben ist, speichern in Datei; sonst Ausgabe auf stdout if (-not [string]::IsNullOrEmpty($OutputPath)) { # OutputPath prüfen – überspringen, wenn es wie eine Hilfefrage aussieht oder ungültige Zeichen enthält if ($OutputPath -match '^[/\-]' -or $OutputPath -match '[<>:"|?*]') { Write-Host "Ungültiger OutputPath angegeben, Ausgabe erfolgt auf stdout" -ForegroundColor Yellow Write-Output $jsonOutput if ($secureBootEnabled -and $uefica2023Status -eq "Updated") {{ exit 0 }} else {{ exit 1 }} } # Sicherstellen, dass der Ausgabeordner existiert if (-not (Test-Path $OutputPath)) { try { New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null } catch { Write-Warning "Ausgabeordner konnte nicht erstellt werden: $OutputPath – $_" } } # Speichern in HOSTNAME_latest.json $outputFile = Join-Path $OutputPath "$($hostname)_latest.json" try { $jsonOutput | Out-File -FilePath $outputFile -Encoding UTF8 -Force Write-Host "JSON gespeichert in: $outputFile" -ForegroundColor Green } catch { Write-Warning "Konnte nicht in Datei schreiben: $outputFile – $_" # Fallback auf stdout Write-Output $jsonOutput } } else { # Ursprüngliches Verhalten – Ausgabe auf stdout Write-Output $jsonOutput }
# Exitcode: "Updated" ist der Erfolgswert laut Playbook if ($secureBootEnabled -and $uefica2023Status -eq "Updated") { exit 0 # Ohne Probleme } else { exit 1 # Mit Problemen }