Si applica a
Windows 10 Windows 10, version 1607, all editions Win 10 Ent LTSC 2019 Win 10 IoT Ent LTSC 2019 Windows 10 IoT Core LTSC Windows 10 Enterprise LTSC 2021 Windows 10 IoT Enterprise LTSC 2021 Windows 10, version 22H2, all editions Windows 11 Home and Pro, version 21H2 Windows 11 Enterprise Multi-Session, version 21H2 Windows 11 Enterprise and Education, version 21H2 Windows 11 IoT Enterprise, version 21H2 Windows 11 Home and Pro, version 22H2 Windows 11 Enterprise Multi-Session, version 22H2 Windows 11 Enterprise and Education, version 22H2 Windows 11 IoT Enterprise, version 22H2 Windows 11 SE, version 23H2 Windows 11 Home and Pro, version 23H2 Windows 11 Enterprise and Education, version 23H2 Windows 11 Enterprise Multi-Session, version 23H2 Windows 11 SE, version 24H2 Windows 11 Enterprise and Education, version 24H2 Windows 11 Enterprise Multi-Session, version 24H2 Windows 11 Home and Pro, version 24H2 Windows 11 IoT Enterprise, version 24H2 Windows Server 2012 ESU Windows Server 2012 R2 ESU Windows Server 2016 Windows Server 2019 Windows Server 2022 Windows Server 2025

Data di pubblicazione originale: 17 novembre 2025

ID KB: 5072718

Modifica data

Modificare la descrizione

24 febbraio 2026

  • Aggiornato lo script di raccolta dei dati dell'inventario di avvio protetto di esempio.

22 febbraio 2026

  • Aggiornato lo script di raccolta dei dati dell'inventario di avvio protetto di esempio.

13 febbraio 2026

  • Aggiornato lo script di raccolta dei dati dell'inventario di avvio protetto di esempio.

Script di esempio per la raccolta dei dati dell'inventario di avvio protetto

Copiare e incollare questo script di esempio e modificarlo in base alle esigenze per l'ambiente: script di raccolta dati di esempio per l'inventario di avvio protetto.

<# . SINOSSI     Rileva lo stato di aggiornamento del certificato di avvio protetto per il monitoraggio a livello di flotta.

. DESCRIZIONE     Questo script di rilevamento raccoglie lo stato di avvio protetto, i valori del Registro di sistema per l'aggiornamento dei certificati,     e informazioni sul dispositivo. Restituisce una stringa JSON per il monitoraggio e la creazione di report.

    Compatibile con Intune Correzioni, raccolta basata su Oggetto Criteri di gruppo e altri strumenti di gestione.Non è necessario alcun script di correzione: questa operazione viene eseguita solo per il monitoraggio.

    Exit 0 = "Without issue" (certificati aggiornati)     Exit 1 = "With issue" (certificates not updated — informational only)

. PARAMETER OutputPath     Opzionale. Percorso di una cartella in cui verrà salvato il file JSON.Se disponibile, salva HOSTNAME_latest.json in questa cartella.Se non viene fornito, viene generato JSON su stdout (comportamento originale).

. ESEMPIO     # Output in stdout (rilevamento Intune/SCCM)     \Detect-SecureBootCertUpdateStatus.ps1

. ESEMPIO     # Save to network share (GPO deployment)     .\Detect-SecureBootCertUpdateStatus.ps1 -OutputPath "\\server\SecureBootLogs$"

. NOTE     Percorsi del Registro di sistema per https://aka.ms/securebootplaybook:       HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot       HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing

    IL SOFTWARE VIENE FORNITO "COSÌ COME È", SENZA GARANZIE DI ALCUN TIPO, EXPRESS O     IMPLICITE, COMPRESE, TRA LE ALTRE, LE GARANZIE DI COMMERCIABILITÀ,     IDONEITÀ PER UNO SCOPO SPECIFICO E NON VIOLAZIONE DI DIRITTI DI PROPRIETÀ. IN NESSUN CASO LA     AUTORI O PROPRIETARI DEL COPYRIGHT SARANNO RITENUTI RESPONSABILI PER QUALSIASI RIVENDICAZIONE, DANNO O ALTRO     RESPONSABILITÀ, SIA NELL'ESERCIZIO DEL CONTRATTO, CHE PER ILLECITO CIVILE O ALTRA AZIONE CIVILE, DERIVANTI DA     IN CONNESSIONE CON IL SOFTWARE O CON L'USO O ALTRE ATTIVITÀ RELATIVE A     SOFTWARE.#> param(     [Parametro(Obbligatorio = $false)]     [stringa]$OutputPath )

# URL di download: https://aka.ms/getsecureboot -> "Esempi di distribuzione e monitoraggio" # Nota: questo script viene eseguito sugli endpoint per raccogliere i dati di stato di avvio protetto.

# 1. Hostname # PS Version: All | Amministrazione: No | Requisiti di sistema: Nessuno prova {     $hostname = $env:NOMECOMPUTER     if ([string]::IsNullOrEmpty($hostname)) {         Write-Warning "Impossibile determinare hostname"         $hostname = "Sconosciuto"     }     Write-Host "Hostname: $hostname" } catch {     Write-Warning "Errore durante il recupero di hostname: $_"     $hostname = "Errore"     Write-Host "Hostname: $hostname" }

# 2. CollectionTime # PS Version: All | Amministrazione: No | Requisiti di sistema: Nessuno prova {     $collectionTime = Get-Date     if ($null -eq $collectionTime) {         Write-Warning "Impossibile recuperare la data/ora corrente"         $collectionTime = "Sconosciuto"     }     Write-Host "Tempo di raccolta: $collectionTime" } catch {     Write-Warning "Errore durante il recupero di data/ora: $_"     $collectionTime = "Errore"     Write-Host "Tempo di raccolta: $collectionTime" }

# Registro di sistema: chiave principale di avvio protetto (3 valori)

# 3. SecureBootEnabled # VERSIONE PS: 3.0+ | Amministrazione: può essere richiesto | Requisiti di sistema: sistema che supporta UEFI/Avvio protetto prova {     $secureBootEnabled = Confirm-SecureBootUEFI -ErrorAction Stop     Write-Host "Avvio protetto abilitato: $secureBootEnabled" } catch {     Write-Warning "Impossibile determinare lo stato di avvio protetto tramite cmdlet: $_"     # Prova il fallback del Registro di sistema     prova {         $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State" -Name UEFISecureBootEnabled -ErrorAction Stop         $secureBootEnabled = [bool]$regValue.UEFISecureBootEnabled         Write-Host "Avvio protetto abilitato: $secureBootEnabled"     } catch {         Write-Warning "Impossibile determinare lo stato di avvio protetto tramite il Registro di sistema. Il sistema potrebbe non supportare UEFI/Avvio protetto".         $secureBootEnabled = $null         Write-Host "Avvio protetto abilitato: non disponibile"     } }

# 4. HighConfidenceOptOut # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name HighConfidenceOptOut -ErrorAction Stop     $highConfidenceOptOut = $regValue.HighConfidenceOptOut     Write-Host "Rifiuto esplicito con confidenza elevata: $highConfidenceOptOut" } catch {     # HighConfidenceOptOut è facoltativo e non è presente nella maggior parte dei sistemi     $highConfidenceOptOut = $null     Write-Host "Rifiuto esplicito con confidenza elevata: non impostato" }

N. 4b. MicrosoftUpdateManagedOptIn # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name MicrosoftUpdateManagedOptIn -ErrorAction Stop     $microsoftUpdateManagedOptIn = $regValue.MicrosoftUpdateManagedOptIn     Write-Host "Consenso esplicito gestito da Microsoft Update: $microsoftUpdateManagedOptIn" } catch {     # MicrosoftUpdateManagedOptIn è facoltativo, non presente nella maggior parte dei sistemi     $microsoftUpdateManagedOptIn = $null     Write-Host "Consenso esplicito gestito da Microsoft Update: non impostato" }

# 5. AvailableUpdates # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdates -ErrorAction Stop     $availableUpdates = $regValue.AvailableUpdates     if ($null -ne $availableUpdates) {         # Converti in formato esadecimale         $availableUpdatesHex = "0x{0:X}" -f $availableUpdates         Write-Host "Aggiornamenti disponibile: $availableUpdatesHex"     } else {         Write-Host "Disponibile Aggiornamenti: Non disponibile"     } } catch {     Write-Warning "AvailableUpdates registry key not found or inaccessible"     $availableUpdates = $null     Write-Host "Disponibile Aggiornamenti: Non disponibile" }

N. 5b. AvailableUpdatesPolicy (valore permanente controllato dall'oggetto Criteri di gruppo) # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdatesPolicy -ErrorAction Stop     $availableUpdatesPolicy = $regValue.AvailableUpdatesPolicy     if ($null -ne $availableUpdatesPolicy) {         # Converti in formato esadecimale         $availableUpdatesPolicyHex = "0x{0:X}" -f $availableUpdatesPolicy         Write-Host "Criteri di Aggiornamenti disponibili: $availableUpdatesPolicyHex"     } else {         Write-Host "Criterio di Aggiornamenti disponibile: non impostato"     } } catch {     # AvailableUpdatesPolicy è facoltativo: impostato solo quando viene applicato l'oggetto Criteri di gruppo     $availableUpdatesPolicy = $null     Write-Host "Criterio di Aggiornamenti disponibile: non impostato" }

# Registro di sistema: chiave di manutenzione (3 valori)

# 6. UEFICA2023Status # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Status -ErrorAction Stop     $uefica 2023Status = $regValue.UEFICA2023Status     Write-Host "Stato DELLA UEFI di Windows 2023: $uefica 2023Status" } catch {     Write-Warning "Chiave del Registro di sistema di stato DI WINDOWS UEFI 2023 non trovata o non accessibile"     $uefica 2023Status = $null     Write-Host "Stato DELLA UEFI di Windows 2023: non disponibile" }

# 7. UEFICA2023Errore # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Error -ErrorAction Stop     $uefica 2023Error = $regValue.UEFICA2023Error     Write-Host "Errore UEFI CA 2023: $uefica 2023Errore" } catch {     # UEFICA2023Errore esiste solo se si è verificato un errore: assenza buona     $uefica 2023Error = $null     Write-Host "Errore UEFI CA 2023: Nessuno" }

# 8. UEFICA2023ErrorEvent # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023ErrorEvent -ErrorAction Stop     $uefica 2023ErrorEvent = $regValue.UEFICA2023ErrorEvent     Write-Host "Evento errore UEFI CA 2023: $uefica 2023ErrorEvent" } catch {     $uefica 2023ErrorEvent = $null     Write-Host "Evento di errore UEFI CA 2023: non disponibile" }

# Registro di sistema: Attributi del dispositivo (7 valori: 9-15)

# 9. OEMManufacturerName # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova {     $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 è vuoto"         $oemManufacturerName = "Sconosciuto"     }     Write-Host "Nome produttore OEM: $oemManufacturerName" } catch {     Write-Warning "OEMManufacturerName chiave del Registro di sistema non trovata o non accessibile"     $oemManufacturerName = $null     Write-Host "Nome produttore OEM: non disponibile" }

# 10. OEMModelSystemFamily # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova {     $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 è vuoto"         $oemModelSystemFamily = "Sconosciuto"     }     Write-Host "Famiglia di sistemi MODELLO OEM: $oemModelSystemFamily" } catch {     Write-Warning "Chiave del Registro di sistema OEMModelSystemFamily non trovata o inaccessibile"     $oemModelSystemFamily = $null     Write-Host "Famiglia di sistemi modello OEM: non disponibile" }

# 11. OEMModelNumber # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OEMModelNumber -ErrorAction Stop     $oemModelNumber = $regValue.OEMModelNumber     if ([string]::IsNullOrEmpty($oemModelNumber)) {         Write-Warning "OEMModelNumber is empty"         $oemModelNumber = "Sconosciuto"     }     Write-Host "Numero modello OEM: $oemModelNumber" } catch {     Write-Warning "CHIAVE OEMModelNumber del Registro di sistema non trovata o non accessibile"     $oemModelNumber = $null     Write-Host "Numero modello OEM: Non disponibile" }

# 12. FirmwareVersion # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name FirmwareVersion -ErrorAction Stop     $firmwareVersion = $regValue.FirmwareVersion     if ([string]::IsNullOrEmpty($firmwareVersion)) {         Write-Warning "FirmwareVersion is empty"         $firmwareVersion = "Sconosciuto"     }     Write-Host "Versione firmware: $firmwareVersion" } catch {     Write-Warning "FirmwareVersion registry key not found or inaccessible"     $firmwareVersion = $null     Write-Host "Versione firmware: Non disponibile" }

# 13. FirmwareReleaseDate # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova {     $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 = "Sconosciuto"     }     Write-Host "Data di rilascio del firmware: $firmwareReleaseDate" } catch {     Write-Warning "FirmwareReleaseDate registry key not found or inaccessible"     $firmwareReleaseDate = $null     Write-Host "Data di rilascio del firmware: non disponibile" }

# 14. OSArchitecture # PS Version: All | Amministrazione: No | Requisiti di sistema: Nessuno prova {     $osArchitecture = $env:PROCESSOR_ARCHITECTURE     if ([string]::IsNullOrEmpty($osArchitecture)) {         # Prova il fallback del Registro di sistema         $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OSArchitecture -ErrorAction Stop         $osArchitecture = $regValue.OSArchitecture     }     if ([string]::IsNullOrEmpty($osArchitecture)) {         Write-Warning "Impossibile determinare OSArchitecture"         $osArchitecture = "Sconosciuto"     }     Write-Host "Architettura del sistema operativo: $osArchitecture" } catch {     Write-Warning "Errore durante il recupero dell'architettura OS: $_"     $osArchitecture = "Sconosciuto"     Write-Host "Architettura del sistema operativo: $osArchitecture" }

# 15. CanAttemptUpdateAfter (FILETIME) # PS Version: All | Amministrazione: può essere richiesto | Requisiti di sistema: Nessuno prova {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name CanAttemptUpdateAfter -ErrorAction Stop     $canAttemptUpdateAfter = $regValue.CanAttemptUpdateAfter     # Convert FILETIME to UTC DateTime : archivia il Registro di sistema come REG_BINARY (byte[]) o REG_QWORD (long)     if ($null -ne $canAttemptUpdateAfter) {         prova {             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 "Impossibile convertire CanAttemptUpdateAfter FILETIME in DateTime"         }     }     Write-Host "Può tentare l'aggiornamento dopo: $canAttemptUpdateAfter" } catch {     Write-Warning "CanAttemptUpdateDopo chiave del Registro di sistema non trovata o inaccessibile"     $canAttemptUpdateAfter = $null     Write-Host "Può tentare l'aggiornamento dopo: Non disponibile" }

# Registri eventi: Registro di sistema (10 valori: 16-25)

# 16-25. Query del registro eventi # ID evento: # 1801 - Aggiornamento avviato, riavvio richiesto N. 1808 - Aggiornamento completato # 1795 - Errore firmware restituito (codice di errore di acquisizione) # 1796 - Errore registrato con codice di errore (codice di acquisizione) # 1800 - Riavvio necessario (NON un errore - l'aggiornamento procederà dopo il riavvio) # 1802 - Aggiornamento bloccato del firmware noto (cattura KI_<numero> da SkipReason) # 1803 - Aggiornamento KEK corrispondente non trovato (OEM deve fornire KEK firmato PK) # VERSIONE PS: 3.0+ | Amministrazione: potrebbe essere necessario per il registro di sistema | Requisiti di sistema: Nessuno prova {     # Esegui una query su tutti gli ID evento di avvio protetto pertinenti     $allEventIds = @(1795, 1796, 1800, 1801, 1802, 1803, 1808)     $events = @(Get-WinEvent -FilterHashtable @{LogName='System'; ID=$allEventIds} -MaxEvents 50 -ErrorAction Stop)

    se ($events. Conteggio -eq 0) {         Write-Warning "Nessun evento di avvio protetto trovato nel registro di sistema"         $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 "ID evento più recente: Non disponibile"         Write-Host "ID contenitore: non disponibile"         Write-Host "Confidenza: non disponibile"         Write-Host "Numero evento 1801: 0"         Write-Host "Numero evento 1808: 0"     } else {         # 16. LatestEventId         $latestEvent = $events | Sort-Object TempoCreato -Decrescente | Select-Object -Primo 1         if ($null -eq $latestEvent) {             Write-Warning "Impossibile determinare l'evento più recente"             $latestEventId = $null             Write-Host "ID evento più recente: Non disponibile"         } else {             $latestEventId = $latestEvent.Id             Write-Host "ID evento più recente: $latestEventId"         }

        # 17. BucketID - Estratto dall'evento 1801/1808         if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) {             if ($latestEvent.Message -match 'BucketId:\s*(.+)') {                 $bucketId = $matches[1]. Trim()                 Write-Host "ID bucket: $bucketId"             } else {                 Write-Warning "BucketId non trovato nel messaggio dell'evento"                 $bucketId = $null                 Write-Host "ID bucket: non trovato nell'evento"             }         } else {             Write-Warning "L'evento o il messaggio più recente è Null, non è possibile estrarre BucketId"             $bucketId = $null             Write-Host "ID bucket: non disponibile"         }

        # 18. Confidenza - Estratto dall'evento 1801/1808         if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) {             if ($latestEvent.Message -match 'BucketConfidenceLevel:\s*(.+)') {                 $confidence = $matches[1]. Trim()                 Write-Host "Confidenza: $confidence"             } else {                 Write-Warning "Livello di probabilità non trovato nel messaggio dell'evento"                 $confidence = $null                 Write-Host "Confidenza: non trovato nell'evento"             }         } else {             Write-Warning "L'evento o il messaggio più recente è Null, non è possibile estrarre confidenza"             $confidence = $null             Write-Host "Confidenza: non disponibile"         }

        N. 18b. SkipReason - Estrarre KI_<numero> da SkipReason nello stesso evento di BucketId         # In questo modo vengono acquisiti gli ID dei problemi noti visualizzati insieme a BucketId/Confidence (non solo evento 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 {$_. Id -eq 1801})         $event 1801Count = $event 1801Array.Count         Write-Host "Numero evento 1801: $event 1801Count"

        # 20. Event1808Count         $event 1808Array = @($events | Where-Object {$_. Id -eq 1808})         $event 1808Count = $event 1808Array.Count         Write-Host "Numero evento 1808: $event 1808Count"                  # Inizializza variabili evento di errore         $event 1795Count = 0         $event 1795ErrorCode = $null         $event 1796Count = 0         $event 1796CodiceErrore = $null         $event 1800Count = 0         $rebootPending = $false         $event 1802Count = 0         $knownIssueId = $null         $event 1803Count = 0         $missingKEK = $false                  # Controlla la presenza di eventi di errore solo se l'aggiornamento NON è stato completato         # Ignora l'analisi degli errori se: 1808 è l'evento più recente O UEFICA2023Status è "Aggiornato"         $updateComplete = ($latestEventId -eq 1808) -or ($uefica 2023Status -eq "Updated")                  if (-$updateComplete) {             Write-Host "Aggiornamento non completato - controllo degli eventi di errore..." -ForegroundColor yellow                          # 21. Evento1795 - Errore firmware (codice di errore di acquisizione)             $event 1795Array = @($events | Where-Object {$_. Id -eq 1795})             $event 1795Count = $event 1795Array.Count             if ($event 1795Count -gt 0) {                 $latestEvent 1795 = $event 1795Array | Sort-Object TempoCreato -Decrescente | Select-Object -Primo 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 "Evento 1795 (errore firmware) Numero: $event 1795Count" $(if ($event 1795ErrorCode) { "Codice: $event 1795ErrorCode" })             }                          # 22. Evento1796 - Codice di errore registrato (codice di errore di acquisizione)             $event 1796Array = @($events | Where-Object {$_. Id -eq 1796})             $event 1796Count = $event 1796Array.Count             if ($event 1796Count -gt 0) {                 $latestEvent 1796 = $event 1796Array | Sort-Object TempoCreato -Decrescente | Select-Object -Primo 1                 if ($latestEvent 1796.Message -match '(?:error|code|status)[:\s]*(?:0x)?( [0-9A-Fa-f]{8}|[0-9A-Fa-f]+)') {                     $event 1796CodiceErrore = $matches[1]                 }                 Write-Host "Evento 1796 (errore registrato) Conteggio: $event 1796Count" $(if ($event 1796ErrorCode) { "Code: $event 1796ErrorCode" })             }                          # 23. Evento1800 - Riavvio necessario (NON un errore - l'aggiornamento procederà dopo il riavvio)             $event 1800Array = @($events | Where-Object {$_. Id -eq 1800})             $event 1800Count = $event 1800Array.Count             $rebootPending = $event 1800Count -gt 0             if ($rebootPending) {                 Write-Host "Evento 1800 (riavvio in sospeso): l'aggiornamento verrà eseguito dopo il riavvio" -ForegroundColor Ciano             }                          # 24. Evento1802 - Problema firmware noto (acquisizione di KI_<numero> da SkipReason)             $event 1802Array = @($events | Where-Object {$_. Id -eq 1802})             $event 1802Count = $event 1802Array.Count             if ($event 1802Count -gt 0) {                 $latestEvent 1802 = $event 1802Array | Sort-Object TempoCreato -Decrescente | Select-Object -Primo 1                 if ($latestEvent 1802.Message -match 'SkipReason:\s*(KI_\d+)') {                     $knownIssueId = $matches[1]                 }                 Write-Host "Evento 1802 (problema firmware noto) Numero: $event 1802Count" $(if ($knownIssueId) { "KI: $knownIssueId" })             }                          # 25. Evento1803 - Aggiornamento KEK mancante (OEM deve fornire KEK firmato PK)             $event 1803Array = @($events | Where-Object {$_. Id -eq 1803})             $event 1803Count = $event 1803Array.Count             $missingKEK = $event 1803Count -gt 0             if ($missingKEK) {                 Write-Host "Evento 1803 (KEK mancante): OEM deve fornire KEK firmato PK" -ForegroundColor Giallo             }         } else {             Write-Host "Aggiornamento completato (evento 1808 o Stato=Aggiornato) - analisi degli errori ignorata" -ForegroundColor verde         }     } } catch {     Write-Warning "Errore durante il recupero dei registri eventi. Può richiedere privilegi di amministratore: $_"     $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 "ID evento più recente: errore"     Write-Host "ID bucket: errore"     Write-Host "Confidenza: errore"     Write-Host "Numero evento 1801: 0"     Write-Host "Numero evento 1808: 0" }

# Query WMI/CIM (5 valori)

# 26. OSVersion # Versione PS: 3.0+ (usare Get-WmiObject per 2.0) | Amministrazione: No | Requisiti di sistema: Nessuno prova {     $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop     if ($null -eq $osInfo -or [string]::IsNullOrEmpty($osInfo.Version)) {         Write-Warning "Impossibile recuperare la versione del sistema operativo"         $osVersion = "Sconosciuto"     } else {         $osVersion = $osInfo.Version     }     Write-Host "Versione del sistema operativo: $osVersion" } catch {     # CIM may fail in some environments - use fallback     $osVersion = [System.Environment]::OSVersion.Version.ToString()     if ([string]::IsNullOrEmpty($osVersion)) { $osVersion = "Unknown" }     Write-Host "Versione del sistema operativo: $osVersion" }

# 27. LastBootTime # Versione PS: 3.0+ (usare Get-WmiObject per 2.0) | Amministrazione: No | Requisiti di sistema: Nessuno prova {     $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop     if ($null -eq $osInfo -o $null -eq $osInfo.LastBootUpTime) {         Write-Warning "Impossibile recuperare l'ora dell'ultimo avvio"         $lastBootTime = $null         Write-Host "Ora ultimo avvio: non disponibile"     } else {         $lastBootTime = $osInfo.LastBootUpTime         Write-Host "Ora ultimo avvio: $lastBootTime"     } } catch {     # CIM may fail in some environments - use fallback     prova {         $lastBootTime = (Get-Process -Id 0 -ErrorAction SilentlyContinue). Starttime     } catch {         $lastBootTime = $null     }     if ($lastBootTime) { Write-Host "Ora ultimo avvio: $lastBootTime" } else { Write-Host "Ora ultimo avvio: Non disponibile" } }

# 28. BaseBoardManufacturer # Versione PS: 3.0+ (usare Get-WmiObject per 2.0) | Amministrazione: No | Requisiti di sistema: Nessuno prova {     $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop     if ($null -eq $baseBoard -or [string]::IsNullOrEmpty($baseBoard.Manufacturer)) {         Write-Warning "Impossibile recuperare il produttore della lavagna"         $baseBoardManufacturer = "Sconosciuto"     } else {         $baseBoardManufacturer = $baseBoard.Manufacturer     }     Write-Host "Produttore lavagna: $baseBoardManufacturer" } catch {     # CIM può non riuscire - le informazioni della scheda base sono supplementari     $baseBoardManufacturer = "Sconosciuto"     Write-Host "Produttore lavagna: $baseBoardManufacturer" }

# 29. BaseBoardProduct # Versione PS: 3.0+ (usare Get-WmiObject per 2.0) | Amministrazione: No | Requisiti di sistema: Nessuno prova {     $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop     if ($null -eq $baseBoard -or [string]::IsNullOrEmpty($baseBoard.Product)) {         Write-Warning "Impossibile recuperare il prodotto baseboard"         $baseBoardProduct = "Sconosciuto"     } else {         $baseBoardProduct = $baseBoard.Prodotto     }     Write-Host "Prodotto Baseboard: $baseBoardProduct" } catch {     # CIM può non riuscire - le informazioni della scheda base sono supplementari     $baseBoardProduct = "Sconosciuto"     Write-Host "Prodotto Baseboard: $baseBoardProduct" }

# 30. SecureBootTaskEnabled # PS Version: All | Amministrazione: No | Requisiti di sistema: esiste un'attività programmata # Controlla se l'attività pianificata Secure-Boot-Update è abilitata $secureBootTaskEnabled = $null $secureBootTaskStatus = "Sconosciuto" prova {     $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 'Pronto' -o $taskData.Status -eq 'In esecuzione')         }     } else {         $secureBootTaskStatus = "NotFound"         $secureBootTaskEnabled = $false     }     if ($secureBootTaskEnabled -eq $false) {         Write-Host "Attività di aggiornamento SecureBoot: $secureBootTaskStatus (abilitato: $secureBootTaskEnabled)" -ForegroundColor yellow     } else {         Write-Host "Attività di aggiornamento SecureBoot: $secureBootTaskStatus (abilitato: $secureBootTaskEnabled)" -ForegroundColor green     } } catch {     $secureBootTaskStatus = "Errore"     $secureBootTaskEnabled = $false     Write-Host "Attività di aggiornamento SecureBoot: controllo degli errori - $_" -ForegroundColor red }

# 31. Stato chiave WinCS (F33E0C8E002 - Aggiornamento del certificato di avvio protetto) # PS Version: All | Amministrazione: Sì (per la query) | Requisiti di sistema: WinCsFlags.exe $wincsKeyApplied = $null $wincsKeyStatus = "Sconosciuto" prova {     # Controlla le posizioni comuni per 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) {         # Chiave specifica della query: richiede i diritti di amministratore         $queryOutput = & $wincsFlagsPath /query --key F33E0C8E002 2>&1         $queryOutputStr = $queryOutput -join "'n"         if ($LASTEXITCODE -eq 0) {             # Controlla se la chiave è applicata (cerca "Configurazione attiva" o indicatore simile)             if ($queryOutputStr -match "Active Configuration.*:.enabled" -or $queryOutputStr -match "Configuration.*applied") {                 $wincsKeyApplied = $true                 $wincsKeyStatus = "Applicato"                 Write-Host "Tasto WinCS F33E0C8E002: applicato" -Primo pianoColore verde             } elseif ($queryOutputStr -match "non trovato|Nessuna configurazione") {                 $wincsKeyApplied = $false                 $wincsKeyStatus = "NotApplied"                 Write-Host "Tasto WinCS F33E0C8E002: non applicato" -Primo pianoColore giallo             } else {                 # Key exists - check output for state                 $wincsKeyApplied = $true                 $wincsKeyStatus = "Applicato"                 Write-Host "Tasto WinCS F33E0C8E002: applicato" -Primo pianoColore verde             }         } else {             # Verificare la presenza di messaggi di errore specifici             if ($queryOutputStr -match "Accesso negato|amministratore") {                 $wincsKeyStatus = "AccessDenied"                 Write-Host "Tasto WinCS F33E0C8E002: accesso negato (eseguito come amministratore)" -ForegroundColor DarkGray             } elseif ($queryOutputStr -match "non trovato|Nessuna configurazione") {                 $wincsKeyApplied = $false                 $wincsKeyStatus = "NotApplied"                 Write-Host "Tasto WinCS F33E0C8E002: non applicato" -Primo pianoColore giallo             } else {                 $wincsKeyStatus = "QueryFailed"                 Write-Host "Tasto WinCS F33E0C8E002: query non riuscita" -ForegroundColor red             }         }     } else {         $wincsKeyStatus = "WinCsFlagsNotFound"         Write-Host "Tasto WinCS F33E0C8E002: WinCsFlags.exe non trovato" -ForegroundColor gray     } } catch {     $wincsKeyStatus = "Errore"     Write-Host "WinCS Key F33E0C8E002: Error checking - $_" -ForegroundColor Red }              

# ============================================================================= # Remediation Detection - Output di stato & codice di uscita # =============================================================================

# Build status object from all collected inventory data $status = [ordered]@{     UEFICA2023Status = $uefica 2023Status     UEFICA2023Error = $uefica 2023Error     UEFICA2023ErrorEvent = $uefica 2023ErrorEvent     AvailableUpdates = if ($null -ne $availableUpdates) { $availableUpdatesHex } 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     Confidenza = $confidence     SkipReasonKnownIssue = $skipReasonKnownIssue # KI_<numero> da SkipReason nell'evento BucketId     Event1801Count = $event 1801Count     Event1808Count = $event 1808Count     # Eventi di errore con dettagli acquisiti     Event1795Count = $event 1795Count # Errore firmware restituito     Event1795ErrorCode = $event 1795ErrorCode # Codice di errore dal firmware     Event1796Count = $event 1796Count # Codice di errore registrato     Event1796ErrorCode = $event 1796ErrorCode # Codice di errore acquisito     Event1800Count = $event 1800Count # Riavvio necessario (NON un errore)     RebootPending = $rebootPending # True se è presente l'evento 1800     Event1802Count = $event 1802Count # Problema noto del firmware     KnownIssueId = $knownIssueId # KI_<numero> da SkipReason     Event1803Count = $event 1803Count # Aggiornamento KEK mancante     MissingKEK = $missingKEK # OEM deve fornire KEK firmato PK     OSVersion = $osVersion     LastBootTime = if ($lastBootTime -is [datetime]) { $lastBootTime.ToString("o") } else { "$lastBootTime" }     BaseBoardManufacturer = $baseBoardManufacturer     BaseBoardProduct = $baseBoardProduct     SecureBootTaskEnabled = $secureBootTaskEnabled     SecureBootTaskStatus = $secureBootTaskStatus     WinCSKeyApplied = $wincsKeyApplied # True se è applicato F33E0C8E002 chiave     WinCSKeyStatus = $wincsKeyStatus # Applied, NotApplied, WinCsFlagsNotFound e così via. }

# Output dello stato - Per l'aggregazione dei dati $jsonOutput = $status | ConvertTo-Json -Comprimi

# Se OutputPath è stato fornito, salva nel file; in caso contrario output a stdout if (-not [string]::IsNullOrEmpty($OutputPath)) {     # Convalida OutputPath: ignora se ha un aspetto simile a una richiesta di assistenza o ha caratteri non validi     if ($OutputPath -match '^[/\-]' -o $OutputPath -match '[<>:"|? *]') {         Write-Host "OutputPath specificato non valido, output in stdout" -ForegroundColor Yellow         Write-Output $jsonOutput         if ($secureBootEnabled -and $uefica 2023Status -eq "Updated") { exit 0 } else { exit 1 }     }          # Verificare che la cartella di output esista     if (-not (Test-Path $OutputPath)) {         prova {             New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null         } catch {             Write-Warning "Impossibile creare la cartella di output: $OutputPath - $_"         }     }          # Salva in HOSTNAME_latest.json     $outputFile = Join-Path $OutputPath "$($hostname)_latest.json"     prova {         $jsonOutput | Out-File -FilePath $outputFile -Encoding UTF8 -Force         Write-Host "JSON saved to: $outputFile" -ForegroundColor Green     } catch {         Write-Warning "Impossibile scrivere nel file: $outputFile - $_"         # Torna a stdout         Write-Output $jsonOutput     } } else {     # Comportamento originale - output a stdout     Write-Output $jsonOutput }

# Codice di uscita: "Aggiornato" è il valore di successo per il playbook if ($secureBootEnabled -and $uefica 2023Status -eq "Updated") {     exit 0 # Without issue } else {     exit 1 # With issue }

Serve aiuto?

Vuoi altre opzioni?

Esplorare i vantaggi dell'abbonamento e i corsi di formazione, scoprire come proteggere il dispositivo e molto altro ancora.