Copie e cole este script de exemplo e modifique conforme necessário para o seu ambiente:

<# . SYNOPSIS     Deteta status de atualização de certificados de Arranque Seguro para monitorização em toda a frota.

.DESCRIPTION     Este script de deteção recolhe status de Arranque Seguro, valores de registo de atualização de certificados,     e informações do dispositivo. Produz uma cadeia JSON para monitorização e relatórios.

    Compatible with Intune Remediations, GPO-based collection, and other management tools. Não é necessário nenhum script de remediação — isto é apenas monitorização.

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

.PARAMETER OutputPath     Opcional. Caminho para uma pasta onde o ficheiro JSON será guardado.Se for fornecido, guarda HOSTNAME_latest.json nesta pasta.Se não for fornecido, produz JSON para stdout (comportamento original).

.EXAMPLE     # Saída para stdout (deteção de Intune/SCCM)     .\Detect-SecureBootCertUpdateStatus.ps1

.EXAMPLE     # Guardar na partilha de rede (implementação de GPO)     .\Detect-SecureBootCertUpdateStatus.ps1 -OutputPath "\\server\SecureBootLogs$"

.NOTES     Caminhos de registo por https://aka.ms/securebootplaybook:       HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot       HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     IMPLÍCITO, INCLUINDO, MAS NÃO SE LIMITANDO ÀS GARANTIAS DE COMERCIALIZAÇÃO,     FITNESS PARA UM PROPÓSITO PARTICULAR E NONINFRINGEMENT. EM NENHUM CASO, O     AUTORES OU TITULARES DE DIREITOS DE AUTOR SÃO RESPONSÁVEIS POR QUALQUER RECLAMAÇÃO, DANOS OU OUTROS     RESPONSABILIDADE, SEJA NUMA AÇÃO DE CONTRATO, TORT OU DE OUTRA FORMA, DECORRENTE DE,     FORA OU EM LIGAÇÃO COM O SOFTWARE, A UTILIZAÇÃO OU OUTRAS TRANSACÇÕES NO     SOFTWARE.#> parâmetro(     [Parameter(Mandatory = $false)]     [string]$OutputPath )

# Download URL: https://aka.ms/getsecureboot -> "Deployment and Monitoring Samples" Nota: este script é executado em pontos finais para recolher dados de status de Arranque Seguro.

# 1. HostName # PS Version: All | Administração: Não | Requisitos de Sistema: Nenhum experimente {     $hostname = $env:COMPUTERNAME     if ([string]::IsNullOrEmpty($hostname)) {         Write-Warning "Não foi possível determinar o nome do anfitrião"         $hostname = "Desconhecido"     }     Write-Host "Hostname: $hostname" } captura {     Write-Warning "Erro ao obter o nome do anfitrião: $_"     $hostname = "Erro"     Write-Host "Hostname: $hostname" }

# 2. CollectionTime # PS Version: All | Administração: Não | Requisitos de Sistema: Nenhum experimente {     $collectionTime = Get-Date     if ($null -eq $collectionTime) {         Write-Warning "Não foi possível obter a data/hora atuais"         $collectionTime = "Desconhecido"     }     Write-Host "Tempo da Coleção: $collectionTime" } captura {     Write-Warning "Erro ao obter a data/hora: $_"     $collectionTime = "Erro"     Write-Host "Tempo da Coleção: $collectionTime" }

# Registry: Secure Boot Main Key (3 values)

# 3. SecureBootEnabled # PS Version: 3.0+ | Administração: Pode ser necessário | Requisitos de Sistema: sistema compatível com UEFI/Arranque Seguro experimente {     $secureBootEnabled = Confirm-SecureBootUEFI -ErrorAction Stop     Write-Host "Arranque Seguro Ativado: $secureBootEnabled" } captura {     Write-Warning "Não é possível determinar a status de Arranque Seguro através do cmdlet: $_"     # Experimente a contingência do registo     experimente {         $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State" -Name UEFISecureBootEnabled -ErrorAction Stop         $secureBootEnabled = [bool]$regValue.UEFISecureBootEnabled         Write-Host "Arranque Seguro Ativado: $secureBootEnabled"     } captura {         Write-Warning "Não é possível determinar a status de Arranque Seguro através do registo. O sistema pode não suportar UEFI/Arranque Seguro."         $secureBootEnabled = $null         Write-Host "Arranque Seguro Ativado: Não Disponível"     } }

# 4. HighConfidenceOptOut # PS Version: All | Administração: Pode ser necessário | Requisitos de Sistema: Nenhum experimente {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name HighConfidenceOptOut -ErrorAction Stop     $highConfidenceOptOut = $regValue.HighConfidenceOptOut     Write-Host "Opção de Exclusão de Confiança Elevada: $highConfidenceOptOut" } captura {     # HighConfidenceOptOut é opcional – não está presente na maioria dos sistemas     $highConfidenceOptOut = $null     Write-Host "Opção de Elevada Confiança: Não Definida" }

# 4b. MicrosoftUpdateManagedOptIn # PS Version: All | Administração: Pode ser necessário | Requisitos de Sistema: Nenhum experimente {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name MicrosoftUpdateManagedOptIn -ErrorAction Stop     $microsoftUpdateManagedOptIn = $regValue.MicrosoftUpdateManagedOptIn     Write-Host "Microsoft Update Managed Opt In: $microsoftUpdateManagedOptIn" } captura {     # MicrosoftUpdateManagedOptIn é opcional – não está presente na maioria dos sistemas     $microsoftUpdateManagedOptIn = $null     Write-Host "Microsoft Update Managed Opt In: Not Set" }

# 5. AvailableUpdates # PS Version: All | Administração: Pode ser necessário | Requisitos de Sistema: Nenhum experimente {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdates -ErrorAction Stop     $availableUpdates = $regValue.AvailableUpdates     if ($null -ne $availableUpdates) {         # Converter em formato hexadecimal         $availableUpdatesHex = "0x{0:X}" -f $availableUpdates         Write-Host "Atualizações Disponível: $availableUpdatesHex"     } senão {         Write-Host "Disponível Atualizações: Não Disponível"     } } captura {     Write-Warning "Chave de registo AvailableUpdates não encontrada ou inacessível"     $availableUpdates = $null     Write-Host "Disponível Atualizações: Não Disponível" }

# 5b. AvailableUpdatesPolicy (GPO-controlled persistent value) # PS Version: All | Administração: Pode ser necessário | Requisitos de Sistema: Nenhum experimente {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot" -Name AvailableUpdatesPolicy -ErrorAction Stop     $availableUpdatesPolicy = $regValue.AvailableUpdatesPolicy     if ($null -ne $availableUpdatesPolicy) {         # Converter em formato hexadecimal         $availableUpdatesPolicyHex = "0x{0:X}" -f $availableUpdatesPolicy         Write-Host "Política de Atualizações Disponível: $availableUpdatesPolicyHex"     } senão {         Write-Host "Política de Atualizações Disponível: Não Definida"     } } captura {     # AvailableUpdatesPolicy é opcional - apenas definido quando o GPO é aplicado     $availableUpdatesPolicy = $null     Write-Host "Política de Atualizações Disponível: Não Definida" }

# Registry: Servicing Key (3 values)

# 6. UEFICA2023Status # PS Version: All | Administração: Pode ser necessário | Requisitos de Sistema: Nenhum experimente {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Status -ErrorAction Stop     $uefica 2023Status = $regValue.UEFICA2023Status     Write-Host "Estado da AC 2023 do UEFI do Windows: $uefica 2023Status" } captura {     Write-Warning "Chave de registo de estado da AC 2023 do UEFI do Windows não encontrada ou inacessível"     $uefica 2023Status = $null     Write-Host "Estado da AC 2023 do UEFI do Windows: Não Disponível" }

# 7. UEFICA2023Error # PS Version: All | Administração: Pode ser necessário | Requisitos de Sistema: Nenhum experimente {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023Error -ErrorAction Stop     $uefica 2023Error = $regValue.UEFICA2023Error     Write-Host "Erro UEFI CA 2023: $uefica 2023Error" } captura {     # UEFICA2023Error só existe se tiver ocorrido um erro – a ausência é boa     $uefica 2023Error = $null     Write-Host "Erro UEFI CA 2023: Nenhum" }

# 8. UEFICA2023ErrorEvent # PS Version: All | Administração: Pode ser necessário | Requisitos de Sistema: Nenhum experimente {     $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing" -Name UEFICA2023ErrorEvent -ErrorAction Stop     $uefica 2023ErrorEvent = $regValue.UEFICA2023ErrorEvent     Write-Host "Evento de Erro da AC UEFI 2023: $uefica 2023ErrorEvent" } captura {     $uefica 2023ErrorEvent = $null     Write-Host "Evento de Erro da AC UEFI 2023: Não Disponível" }

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

# 9. OEMManufacturerName # PS Version: All | Administração: Pode ser necessário | Requisitos de Sistema: Nenhum experimente {     $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 está vazio"         $oemManufacturerName = "Desconhecido"     }     Write-Host "Nome do Fabricante OEM: $oemManufacturerName" } captura {     Write-Warning "Chave de registo OEMManufacturerName não encontrada ou inacessível"     $oemManufacturerName = $null     Write-Host "Nome do Fabricante OEM: Não Disponível" }

# 10. OEMModelSystemFamily # PS Version: All | Administração: Pode ser necessário | Requisitos de Sistema: Nenhum experimente {     $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 está vazio"         $oemModelSystemFamily = "Desconhecido"     }     Write-Host "OEM Model System Family: $oemModelSystemFamily" } captura {     Write-Warning "Chave de registo OEMModelSystemFamily não encontrada ou inacessível"     $oemModelSystemFamily = $null     Write-Host "Família do Sistema do Modelo OEM: Não Disponível" }

# 11. OEMModelNumber # PS Version: All | Administração: Pode ser necessário | Requisitos de Sistema: Nenhum experimente {     $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 está vazio"         $oemModelNumber = "Desconhecido"     }     Write-Host "Número do Modelo OEM: $oemModelNumber" } captura {     Write-Warning "Chave de registo OEMModelNumber não encontrada ou inacessível"     $oemModelNumber = $null     Write-Host "Número do Modelo OEM: Não Disponível" }

# 12. FirmwareVersion # PS Version: All | Administração: Pode ser necessário | Requisitos de Sistema: Nenhum experimente {     $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 está vazio"         $firmwareVersion = "Desconhecido"     }     Write-Host "Versão de Firmware: $firmwareVersion" } captura {     Write-Warning "FirmwareVersion registry key not found or inaccessible"     $firmwareVersion = $null     Write-Host "Versão de Firmware: Não Disponível" }

# 13. FirmwareReleaseDate # PS Version: All | Administração: Pode ser necessário | Requisitos de Sistema: Nenhum experimente {     $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 está vazio"         $firmwareReleaseDate = "Desconhecido"     }     Write-Host "Data de Lançamento do Firmware: $firmwareReleaseDate" } captura {     Write-Warning "FirmwareReleaseDate registry key not found or inaccessible"     $firmwareReleaseDate = $null     Write-Host "Data de Lançamento do Firmware: Não Disponível" }

# 14. OSArchitecture # PS Version: All | Administração: Não | Requisitos de Sistema: Nenhum experimente {     $osArchitecture = $env:PROCESSOR_ARCHITECTURE     if ([string]::IsNullOrEmpty($osArchitecture)) {         # Experimente a contingência do registo         $regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing\DeviceAttributes" -Name OSArchitecture -ErrorAction Stop         $osArchitecture = $regValue.OSArchitecture     }     if ([string]::IsNullOrEmpty($osArchitecture)) {         Write-Warning "Não foi possível determinar a OSArchitecture"         $osArchitecture = "Desconhecido"     }     Write-Host "Arquitetura do SO: $osArchitecture" } captura {     Write-Warning "Erro ao obter OSArchitecture: $_"     $osArchitecture = "Desconhecido"     Write-Host "Arquitetura do SO: $osArchitecture" }

# 15. CanAttemptUpdateAfter (FILETIME) # PS Version: All | Administração: Pode ser necessário | Requisitos de Sistema: Nenhum experimente {     $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) {         experimente {             if ($canAttemptUpdateAfter -is [byte[]]) {                 $fileTime = [BitConverter]::ToInt64($canAttemptUpdateAfter, 0)                 $canAttemptUpdateAfter = [DateTime]::FromFileTime($fileTime). ToUniversalTime()             } elseif ($canAttemptUpdateAfter -is [long]) {                 $canAttemptUpdateAfter = [DateTime]::FromFileTime($canAttemptUpdateAfter). ToUniversalTime()             }         } captura {             Write-Warning "Não foi possível converter CanAttemptUpdateAfter FILETIME em DateTime"         }     }     Write-Host "Pode Tentar Atualizar Após: $canAttemptUpdateAfter" } captura {     Write-Warning "CanAttemptUpdateAfter registry key not found or inaccessible"     $canAttemptUpdateAfter = $null     Write-Host "Pode Tentar Atualizar Após: Não Disponível" }

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

# 16-25. Event Log queries # IDs de Evento: N.º 1801 - Atualização iniciada, reinício necessário N.º 1808 – Atualização concluída com êxito N.º 1795 – O firmware devolveu o erro (código de erro de captura) N.º 1796 – Erro registado com o código de erro (código de captura) N.º 1800 – Reinício necessário (NÃO é um erro – a atualização prosseguirá após o reinício) N.º 1802 – Problema de firmware conhecido– atualização bloqueada (capture KI_<número> de SkipReason) N.º 1803 – Atualização KEK correspondente não encontrada (o OEM precisa de fornecer KEK assinado por PK) # PS Version: 3.0+ | Administração: Pode ser necessário para o Registo do sistema | Requisitos de Sistema: Nenhum experimente {     # Consultar todos os IDs de eventos de Arranque Seguro relevantes     $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 "Não foram encontrados eventos de Arranque Seguro no Registo do 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 do Evento Mais Recente: Não Disponível"         Write-Host "ID do Registo: Não Disponível"         Write-Host "Confiança: Não Disponível"         Write-Host "Contagem de Eventos 1801: 0"         Write-Host "Contagem de Eventos 1808: 0"     } senão {         # 16. LatestEventId         $latestEvent = $events | Sort-Object TimeCreated -Descending | Select-Object -Primeiro 1         if ($null -eq $latestEvent) {             Write-Warning "Não foi possível determinar o evento mais recente"             $latestEventId = $null             Write-Host "ID do Evento Mais Recente: Não Disponível"         } senão {             $latestEventId = $latestEvent.Id             Write-Host "ID do Evento Mais Recente: $latestEventId"         }

        # 17. BucketID - Extracted from Event 1801/1808 if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) {             if ($latestEvent.Message -match 'BucketId:\s*(.+)') {                 $bucketId = $matches[1]. Cortar()                 Write-Host "ID do Registo: $bucketId"             } senão {                 Write-Warning "BucketId não encontrado na mensagem de evento"                 $bucketId = $null                 Write-Host "ID do Registo: Não Encontrado no Evento"             }         } senão {             Write-Warning "O evento ou mensagem mais recente é nulo, não é possível extrair BucketId"             $bucketId = $null             Write-Host "ID do Registo: Não Disponível"         }

        # 18. Confidence - Extracted from Event 1801/1808 if ($null -ne $latestEvent -and $null -ne $latestEvent.Message) {             if ($latestEvent.Message -match 'BucketConfidenceLevel:\s*(.+)') {                 $confidence = $matches[1]. Cortar()                 Write-Host "Confiança: $confidence"             } senão {                 Write-Warning "Nível de confiança não encontrado na mensagem de evento"                 $confidence = $null                 Write-Host "Confiança: Não Encontrado no Evento"             }         } senão {             Write-Warning "O evento ou mensagem mais recente é nulo, não é possível extrair Confiança"             $confidence = $null             Write-Host "Confiança: Não Disponível"         }

        # 18b. SkipReason - Extract KI_<number> from SkipReason in the same event as BucketId # Esta ação captura IDs de Problemas Conhecidos que aparecem juntamente com BucketId/Confidence (não apenas o 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 "Problema Conhecido skipReason: $skipReasonKnownIssue" -ForegroundColor Amarelo             }         }

        # 19. Event1801Count $event 1801Array = @($events | Where-Object {$_. ID -eq 1801})         $event 1801Count = $event 1801Array.Count         Write-Host "Contagem de Eventos 1801: $event 1801Count"

        # 20. Event1808Count $event 1808Array = @($events | Where-Object {$_. ID -eq 1808})         $event 1808Count = $event 1808Array.Count         Write-Host "Contagem de Eventos 1808: $event 1808Count"         # Initialize error event variables (Inicializar variáveis de eventos de erro)         $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         # Apenas marcar para eventos de erro se a atualização NÃO estiver concluída         # Ignore a análise de erros se: 1808 for o evento mais recente OU UEFICA2023Status for "Atualizado"         $updateComplete = ($latestEventId -eq 1808) ou ($uefica 2023Status -eq "Atualizado")         if (-not $updateComplete) {             Write-Host "Update not complete - checking for error events..." -ForegroundColor Yellow             # 21.                                         Evento1795 – Erro de Firmware (código de erro de captura)             $event 1795Array = @($events | Where-Object {$_. ID -eq 1795})             $event 1795Count = $event 1795Array.Count             if ($event 1795Count -gt 0) {                 $latestEvent 1795 = $event 1795Array | Sort-Object TimeCreated -Descending | Select-Object -Primeiro 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 "Contagem do Evento 1795 (Erro de Firmware): $event 1795Count" $(se ($event 1795ErrorCode) { "Código: $event 1795ErrorCode" })             }             # 22.              Evento1796 – Código de Erro Registado (código de erro de captura)             $event 1796Array = @($events | Where-Object {$_. ID -eq 1796})             $event 1796Count = $event 1796Array.Count             if ($event 1796Count -gt 0) {                 $latestEvent 1796 = $event 1796Array | Sort-Object TimeCreated -Descending | Select-Object -Primeiro 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 "Contagem do Evento 1796 (Erro Registado): $event 1796Count" $(se ($event 1796ErrorCode) { "Código: $event 1796ErrorCode" })             }             # 23.              Evento1800 – Reinício Necessário (NÃO é um erro – a atualização irá prosseguir após o reinício)             $event 1800Array = @($events | Where-Object {$_. ID -eq 1800})             $event 1800Count = $event 1800Array.Count             $rebootPending = $event 1800Count -gt 0             se ($rebootPending) {                 Write-Host "Evento 1800 (Reinício Pendente): A atualização irá prosseguir após o reinício" -ForegroundColor Cyan             }                          # 24. Evento1802 – Problema de Firmware Conhecido (capture KI_<número> de 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 TimeCreated -Descending | Select-Object -Primeiro 1                 if ($latestEvent 1802.Message -match 'SkipReason:\s*(KI_\d+)') {                     $knownIssueId = $matches[1]                 }                 Write-Host "Número de Eventos 1802 (Problema de Firmware Conhecido): $event 1802Count" $(se ($knownIssueId) { "KI: $knownIssueId" })             }                          # 25. Evento1803 – Atualização kek em falta (o OEM precisa de fornecer KEK assinado pelo PK)             $event 1803Array = @($events | Where-Object {$_. ID -eq 1803})             $event 1803Count = $event 1803Array.Count             $missingKEK = $event 1803Count -gt 0             se ($missingKEK) {                 Write-Host "Evento 1803 (KEK em Falta): O OEM precisa de fornecer KEK assinado por PK" -ForegroundColor Amarelo             }         } senão {             Write-Host "Atualização concluída (Evento 1808 ou Estado=Atualizado) – a ignorar a análise de erros" -ForegroundColor Green         }     } } captura {     Write-Warning "Erro ao obter registos de eventos. Pode exigir privilégios de administrador: $_"     $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 do Evento Mais Recente: Erro"     Write-Host "ID do Registo: Erro"     Write-Host "Confiança: Erro"     Write-Host "Contagem de Eventos 1801: 0"     Write-Host "Contagem de Eventos 1808: 0" }

# WMI/CIM Queries (5 values)

# 26. OSVersion # PS Versão: 3.0+ (utilize Get-WmiObject para 2.0) | Administração: Não | Requisitos de Sistema: Nenhum experimente {     $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop     if ($null -eq $osInfo -or [string]::IsNullOrEmpty($osInfo.Version)) {         Write-Warning "Não foi possível obter a versão do SO"         $osVersion = "Desconhecido"     } senão {         $osVersion = $osInfo.Version     }     Write-Host "Versão do SO: $osVersion" } captura {     # CIM may fail in some environments - use fallback     $osVersion = [System.Environment]::OSVersion.Version.ToString()     if ([string]::IsNullOrEmpty($osVersion)) { $osVersion = "Unknown" }     Write-Host "Versão do SO: $osVersion" }

# 27. LastBootTime # PS Versão: 3.0+ (utilize Get-WmiObject para 2.0) | Administração: Não | Requisitos de Sistema: Nenhum experimente {     $osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop     if ($null -eq $osInfo -or $null -eq $osInfo.LastBootUpTime) {         Write-Warning "Não foi possível obter a hora do último arranque"         $lastBootTime = $null         Write-Host "Hora do Último Arranque: Não Disponível"     } senão {         $lastBootTime = $osInfo.LastBootUpTime         Write-Host "Hora do Último Arranque: $lastBootTime"     } } captura {     # CIM may fail in some environments - use fallback     experimente {         $lastBootTime = (Get-Process -Id 0 -ErrorAction SilentlyContinue). StartTime     } captura {         $lastBootTime = $null     }     if ($lastBootTime) { Write-Host "Last Boot Time: $lastBootTime" } else { Write-Host "Last Boot Time: Not Available" } }

# 28. BaseBoardManufacturer # PS Versão: 3.0+ (utilize Get-WmiObject para 2.0) | Administração: Não | Requisitos de Sistema: Nenhum experimente {     $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop     if ($null -eq $baseBoard -or [string]::IsNullOrEmpty($baseBoard.Manufacturer)) {         Write-Warning "Não foi possível obter o fabricante da placa base"         $baseBoardManufacturer = "Desconhecido"     } senão {         $baseBoardManufacturer = $baseBoard.Manufacturer     }     Write-Host "Fabricante da Placa Base: $baseBoardManufacturer" } captura {     # CIM may fail - baseboard info is supplementary     $baseBoardManufacturer = "Desconhecido"     Write-Host "Fabricante da Placa Base: $baseBoardManufacturer" }

# 29. BaseBoardProduct # PS Versão: 3.0+ (utilize Get-WmiObject para 2.0) | Administração: Não | Requisitos de Sistema: Nenhum experimente {     $baseBoard = Get-CimInstance Win32_BaseBoard -ErrorAction Stop     if ($null -eq $baseBoard -or [string]::IsNullOrEmpty($baseBoard.Product)) {         Write-Warning "Não foi possível obter o produto da placa base"         $baseBoardProduct = "Desconhecido"     } senão {         $baseBoardProduct = $baseBoard.Product     }     Write-Host "Baseboard Product: $baseBoardProduct" } captura {     # CIM may fail - baseboard info is supplementary     $baseBoardProduct = "Desconhecido"     Write-Host "Baseboard Product: $baseBoardProduct" }

# 30. SecureBootTaskEnabled # PS Version: All | Administração: Não | Requisitos de Sistema: a Tarefa Agendada existe # Verifica se a tarefa agendada Atualização de Arranque Seguro está ativada $secureBootTaskEnabled = $null $secureBootTaskStatus = "Desconhecido" experimente {     $taskOutput = schtasks.exe /Query /TN "\Microsoft\Windows\PI\Secure-Boot-Update" /FO CSV 2>&1     if ($LASTEXITCODE -eq 0) {         $taskData = $taskOutput | ConverterFrom-Csv         se ($taskData) {             $secureBootTaskStatus = $taskData.Status             $secureBootTaskEnabled = ($taskData.Status -eq 'Ready' -or $taskData.Status -eq 'Running')         }     } senão {         $secureBootTaskStatus = "NotFound"         $secureBootTaskEnabled = $false     }     if ($secureBootTaskEnabled -eq $false) {         Write-Host "SecureBoot Update Task: $secureBootTaskStatus (Enabled: $secureBootTaskEnabled)" -ForegroundColor Yellow     } senão {         Write-Host "SecureBoot Update Task: $secureBootTaskStatus (Enabled: $secureBootTaskEnabled)" -ForegroundColor Green     } } captura {     $secureBootTaskStatus = "Erro"     $secureBootTaskEnabled = $false     Write-Host "SecureBoot Update Task: Error checking - $_" -ForegroundColor Red }

# 31. WinCS Key Status (F33E0C8E002 - Secure Boot Certificate Update) # PS Version: All | Administração: Sim (para consulta) | Requisitos de Sistema: WinCsFlags.exe $wincsKeyApplied = $null $wincsKeyStatus = "Desconhecido" experimente {     # Verifique as localizações comuns para WinCsFlags.exe     $wincsFlagsPath = $null     $possiblePaths = @(         "$env:SystemRoot\System32\WinCsFlags.exe",         "$env:SystemRoot\SysWOW64\WinCsFlags.exe"     )     foreach ($p no $possiblePaths) {         if (Test-Path $p) { $wincsFlagsPath = $p; break }     }     se ($wincsFlagsPath) {         # Chave específica da consulta – requer direitos de administrador         $queryOutput = & $wincsFlagsPath /query --key F33E0C8E002 2>&1         $queryOutputStr = $queryOutput -join "'n"         if ($LASTEXITCODE -eq 0) {             # Verifique se a chave está aplicada (procure "Configuração Ativa" ou indicador semelhante)             if ($queryOutputStr -match "Active Configuration.*:.*enabled" -or $queryOutputStr -match "Configuration.*applied") {                 $wincsKeyApplied = $true                 $wincsKeyStatus = "Aplicado"                 Write-Host "WinCS Key F33E0C8E002: Applied" -ForegroundColor Green             } elseif ($queryOutputStr -match "not found|Sem configuração") {                 $wincsKeyApplied = $false                 $wincsKeyStatus = "NotApplied"                 Write-Host "WinCS Key F33E0C8E002: Not Applied" -ForegroundColor Yellow             } senão {                 #Key exists - marcar saída para o estado                 $wincsKeyApplied = $true                 $wincsKeyStatus = "Aplicado"                 Write-Host "WinCS Key F33E0C8E002: Applied" -ForegroundColor Green             }         } senão {             # Verificar se existem mensagens de erro específicas             if ($queryOutputStr -match "Access denied|administrator") {                 $wincsKeyStatus = "AccessDenied"                 Write-Host "WinCS Key F33E0C8E002: Access denied (run as admin)" -ForegroundColor DarkGray             } elseif ($queryOutputStr -match "not found|Sem configuração") {                 $wincsKeyApplied = $false                 $wincsKeyStatus = "NotApplied"                 Write-Host "WinCS Key F33E0C8E002: Not Applied" -ForegroundColor Yellow             } senão {                 $wincsKeyStatus = "QueryFailed"                 Write-Host "WinCS Key F33E0C8E002: Query failed" -ForegroundColor Red             }         }     } senão {         $wincsKeyStatus = "WinCsFlagsNotFound"         Write-Host "WinCS Key F33E0C8E002: WinCsFlags.exe not found" -ForegroundColor Gray     } } captura {     $wincsKeyStatus = "Erro"     Write-Host "WinCS Key F33E0C8E002: Error checking - $_" -ForegroundColor Red }              

# ============================================================================= # Deteção de Remediação – Estado saída & Código de Saída # =============================================================================

# Build status object from all collected inventory data $status = [encomendado]@{     UEFICA2023Status = $uefica 2023Status     UEFICA2023Error = $uefica 2023Error     UEFICA2023ErrorEvent = $uefica 2023ErrorEvent     AvailableUpdates = se ($null -ne $availableUpdates) { $availableUpdatesHex } senão { $null }     AvailableUpdatesPolicy = se ($null -ne $availableUpdatesPolicy) { $availableUpdatesPolicyHex } senão { $null }     Hostname = $hostname     CollectionTime = se ($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 = se ($canAttemptUpdateAfter -is [datetime]) { $canAttemptUpdateAfter.ToString("o") } else { "$canAttemptUpdateAfter" }     LatestEventId = $latestEventId     BucketId = $bucketId     Confiança = $confidence     SkipReasonKnownIssue = $skipReasonKnownIssue # KI_<número> de SkipReason no evento BucketId     Event1801Count = $event 1801Count     Event1808Count = $event 1808Count     # Eventos de erro com detalhes capturados     Event1795Count = $event 1795Count # O firmware devolveu o erro     Event1795ErrorCode = $event 1795ErrorCode # Código de erro do firmware     Event1796Count = $event 1796Contar # Código de erro registado     Event1796ErrorCode = $event 1796ErrorCode # Código de erro capturado     Event1800Count = $event 1800Count # Reinício necessário (NÃO é um erro)     RebootPending = $rebootPending # Verdadeiro se o Evento 1800 estiver presente     Event1802Count = $event 1802Count # Problema de firmware conhecido     KnownIssueId = número $knownIssueId # KI_<> de SkipReason     Event1803Count = $event 1803Count # Atualização KEK em falta     MissingKEK = $missingKEK # OEM precisa de fornecer KEK assinado por PK     OSVersion = $osVersion     LastBootTime = se ($lastBootTime -is [datetime]) { $lastBootTime.ToString("o") } else { "$lastBootTime" }     BaseBoardManufacturer = $baseBoardManufacturer     BaseBoardProduct = $baseBoardProduct     SecureBootTaskEnabled = $secureBootTaskEnabled     SecureBootTaskStatus = $secureBootTaskStatus     WinCSKeyApplied = $wincsKeyApplied # Verdadeiro se for aplicada F33E0C8E002 chave     WinCSKeyStatus = $wincsKeyStatus # Aplicado, NotApplied, WinCsFlagsNotFound, etc. }

# Output the status - For data aggregation $jsonOutput = $status | ConvertTo-Json -Comprimir

# If OutputPath provided, save to file; otherwise output to stdout if (-not [string]::IsNullOrEmpty($OutputPath)) {     # Validate OutputPath - ignore se parece com um pedido de ajuda ou se tem carateres inválidos     if ($OutputPath -match '^[/\-]' -or $OutputPath -match '[<>:"|? *]') {         Write-Host "OutputPath especificado inválido, a exportar para stdout" -ForegroundColor Yellow         Write-Output $jsonOutput         if ($secureBootEnabled -and $uefica 2023Status -eq "Updated") { exit 0 } else { exit 1 }     }     # Certifique-se de que a pasta de saída existe     if (-not (Test-Path $OutputPath)) {         experimente {             New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null         } captura {             Write-Warning "Não foi possível criar a pasta de saída: $OutputPath - $_"         }     }     # Guardar no HOSTNAME_latest.json     $outputFile = Join-Path $OutputPath "$($hostname)_latest.json"     experimente {         $jsonOutput | Out-File -FilePath $outputFile -Encoding UTF8 -Force         Write-Host "JSON guardado em: $outputFile" -ForegroundColor Green     } captura {         Write-Warning "Não foi possível escrever no ficheiro: $outputFile - $_"         # Recue para stdout         Write-Output $jsonOutput     } } senão {     # Comportamento original - saída para stdout     Write-Output $jsonOutput }          

# Exit code: "Updated" is the success value per the playbook if ($secureBootEnabled -and $uefica 2023Status -eq "Updated") {     sair de 0 # Sem problema } senão {     sair de 1 # Com o problema }

​​​​​​​

Precisa de mais ajuda?

Quer mais opções

Explore os benefícios da assinatura, procure cursos de treinamento, saiba como proteger seu dispositivo e muito mais.