Event details
Hi community, SochiOgbuanya Ashis_Chatterjee,
I am providing my PowerShell script below, which makes diagnosing the state across computers easier. It can be used locally or remotely, as a remediation script in Intune, or for exporting events. If you do not need all events, you can customise the script.
When using Event Viewer or Azure Monitoring, this XPath syntax can be used to fetch all relevant events.
In Event Viewer, you can create a custom view on a specific computer to monitor these events.
<QueryList>
<Query Id="0" Path="System">
<Select Path="System">*[System[Provider[@Name='Microsoft-Windows-TPM-WMI'] and (Level=1 or Level=2 or Level=3 or Level=4 or Level=0 or Level=5) and (EventID=1032 or EventID=1033 or EventID=1034 or EventID=1036 or EventID=1037 or EventID=1043 or EventID=1044 or EventID=1045 or EventID=1795 or EventID=1796 or EventID=1797 or EventID=1798 or EventID=1799 or EventID=1801 or EventID=1808)]]
</Select>
</Query>
</QueryList>
function Get-SecureBootDbxEvents {
<#
.SYNOPSIS
Collects Secure Boot DBX–related TPM-WMI events from the System event log,
grouped by Event ID, with optional diagnostics, time filtering, and export.
.DESCRIPTION
This function retrieves TPM-WMI events associated with Secure Boot DBX update
processing, as referenced in Microsoft KB5016061.
To ensure reliable performance on systems with large event logs, each Event ID
is queried in parallel using thread jobs, avoiding the 256‑event limitation of
Get-WinEvent.
The function supports optional diagnostics for Secure Boot, DBX, and TPM
readiness, UTC-normalized time filtering, remote computer targeting, and
structured export of collected events.
.PARAMETER ComputerName
Specifies the target computer to query.
Defaults to the local machine.
.PARAMETER StartTime
Returns only events with a TimeCreated value greater than or equal to the
specified timestamp.
The timestamp is normalized to UTC to ensure consistent filtering across
systems and time zones.
.PARAMETER ExportCsv
Specifies a file path for exporting all collected events in CSV format.
.PARAMETER ExportJson
Specifies a file path for exporting all collected events in JSON format.
.PARAMETER Diagnostics
Runs Secure Boot, DBX, and TPM readiness checks before event collection.
.EXAMPLE
Get-SecureBootDbxEvents -StartTime (Get-Date).AddDays(-7)
Retrieves all Secure Boot DBX–related TPM-WMI events from the past seven days.
.EXAMPLE
Get-SecureBootDbxEvents -Diagnostics -Verbose
Runs diagnostics and displays detailed progress information.
.EXAMPLE
Get-SecureBootDbxEvents -ComputerName SERVER01 -Diagnostics -Verbose
Runs diagnostics and collects events from a remote server.
.NOTES
Event IDs are derived from Microsoft KB5016061.
Requires read access to the SYSTEM event log and the
Microsoft-Windows-TPM-WMI provider.
.LINK
https://github.com/cjee21/Check-UEFISecureBootVariables
Related project to identify the current state around Secure Boot
.LINK
https://techcommunity.microsoft.com/users/karl-we/289393?wt.mc_id=mvp_338345
Contact the author
.LINK
https://support.microsoft.com/topic/secure-boot-db-and-dbx-variable-update-events-37e47cf8-608b-4a87-8175-bdead630eb69?wt.mc_id=mvp_338345
Microsoft Guidance on related Event IDs
.LINK
https://techcommunity.microsoft.com/blog/windows-itpro-blog/secure-boot-playbook-for-certificates-expiring-in-2026/4469235#community-4469235-_option2?wt.mc_id=mvp_338345
Microsoft Guidance on Secure Boot Deployment
.VERSION
1.2.0
# Version History (Semantic Versioning)
# MAJOR version — increment when making incompatible changes
# MINOR version — increment when adding functionality in a backward-compatible manner
# PATCH version — increment when making backward-compatible bug fixes
1.2.0
- Output per EventID to avoid hitting the maximum item count
- Added per‑ID statistics (count, first, last)
- Added color‑coded severity output
- Grouped output per EventID
- Remote computer support
1.1.0
- Added CSV and JSON export options
- UTC-normalized StartTime filtering
1.0.0
- Initial release with:
- Secure Boot / DBX / TPM diagnostics
#>
[CmdletBinding()]
param(
[string]$ComputerName = $env:COMPUTERNAME,
[datetime]$StartTime,
[string]$ExportCsv,
[string]$ExportJson,
[switch]$Diagnostics
)
#region Event IDs from KB5016061
# These are the documented Secure Boot DBX update and remediation events.
$EventIds = @(
1032, 1033, 1034, 1036, 1037,
1043, 1044, 1045,
1795, 1796, 1797, 1798, 1799,
1801, 1808
)
#endregion Event IDs from KB5016061
#region Time filter normalization
# Detect whether StartTime was explicitly provided.
$HasStartTime = $PSBoundParameters.ContainsKey('StartTime')
# Convert StartTime to UTC for consistent filtering across systems.
$StartTimeUtc = $null
if ($HasStartTime) {
$StartTimeUtc = $StartTime.ToUniversalTime()
}
#endregion Time filter normalization
#region Diagnostics
if ($Diagnostics) {
Write-Verbose "Running Secure Boot, DBX, and TPM diagnostics on $ComputerName..."
# Secure Boot state (local only)
if ($ComputerName -ne $env:COMPUTERNAME) {
Write-Warning "Diagnostics are local-only (Confirm-SecureBootUEFI/Get-SecureBootUEFI). Remote diagnostics not supported."
}
try {
Write-Host "Secure Boot Enabled:" (Confirm-SecureBootUEFI) -ForegroundColor Green
} catch {
Write-Warning "Secure Boot state could not be determined."
}
try {
Write-Host "Secure Boot CA2023 deployed" ([System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).bytes) -match ‘Windows UEFI CA 2023’) -ForegroundColor Green
} catch {
Write-Warning "Secure Boot state could not be determined."
}
# DBX variable
try {
$dbx = Get-SecureBootUEFI -Name dbx
Write-Host "DBX Bytes:" $dbx.Bytes.Length -ForegroundColor Cyan
} catch {
Write-Warning "DBX variable could not be retrieved."
}
# TPM state
try {
$tpm = Get-Tpm -ComputerName $ComputerName
Write-Host "TPM Present:" $tpm.TpmPresent
Write-Host "TPM Ready :" $tpm.TpmReady
Write-Host "TPM Version:" $tpm.ManufacturerVersion
} catch {
Write-Warning "TPM state could not be retrieved."
}
Write-Host ""
}
#endregion Diagnostics
#region Parallel Fetch
Write-Verbose "Fetching events per Event ID in parallel from $ComputerName..."
# Thread-safe collection for results
$Results = [System.Collections.Concurrent.ConcurrentBag[object]]::new()
# Store job handles
$Jobs = @()
foreach ($EventID in $EventIds) {
# Start a thread job for each Event ID
$Jobs += Start-ThreadJob -ArgumentList $EventID,$ComputerName,$HasStartTime,$StartTimeUtc -ScriptBlock {
param(
[int]$EventID,
[string]$ComputerName,
[bool]$HasStartTime,
$StartTimeUtc
)
# Build filter for Get-WinEvent
$Filter = @{
LogName = 'System'
ProviderName = 'Microsoft-Windows-TPM-WMI'
Id = $EventID
}
# Add StartTime only if provided
if ($HasStartTime) {
$Filter.StartTime = [datetime]$StartTimeUtc
}
# Query events and return selected fields
Get-WinEvent -ComputerName $ComputerName -FilterHashtable $Filter -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Id, LevelDisplayName, Message
} # end ScriptBlock
} # end foreach EventID
# Collect results from all jobs
foreach ($job in $Jobs) {
$out = Receive-Job -Job $job -Wait -AutoRemoveJob
if ($out) {
foreach ($evt in $out) {
$Results.Add($evt)
}
}
}
#endregion Parallel Fetch
#region Output Handling
if (-not $Results.Count) {
Write-Warning "No TPM-WMI events found for the specified criteria."
return
}
# Group and sort events by Event ID
$Grouped = $Results | Sort-Object Id, TimeCreated | Group-Object Id
foreach ($Group in $Grouped) {
$Events = $Group.Group | Sort-Object TimeCreated
Write-Host ""
Write-Host "===== Event ID $($Group.Name) ====="
Write-Host "Count:" $Events.Count
Write-Host "First:" $Events[0].TimeCreated
Write-Host "Last :" $Events[-1].TimeCreated
Write-Host ""
# Color-coded severity output
foreach ($Evt in $Events) {
$Color = switch ($Evt.LevelDisplayName) {
'Critical' { 'Magenta' }
'Error' { 'Red' }
'Warning' { 'Yellow' }
'Information' { 'Cyan' }
default { 'Gray' }
}
Write-Host ("[{0}] {1} - {2}" -f $Evt.TimeCreated, $Evt.LevelDisplayName, $Evt.Message) -ForegroundColor $Color
}
}
# Export CSV if requested
if ($ExportCsv) {
Write-Verbose "Exporting results to CSV: $ExportCsv"
$Results | Sort-Object Id, TimeCreated |
Export-Csv -Path $ExportCsv -NoTypeInformation -Encoding UTF8
}
# Export JSON if requested
if ($ExportJson) {
Write-Verbose "Exporting results to JSON: $ExportJson"
$Results | Sort-Object Id, TimeCreated |
ConvertTo-Json -Depth 5 | Out-File -FilePath $ExportJson -Encoding UTF8
}
# Return sorted objects for pipeline use
$Results | Sort-Object Id, TimeCreated
#endregion Output Handling
} # end function Get-SecureBootDbxEvents
NICE! You may have saved us a LOT of work my friend!
I'll try this on M365 managed PCs and report back how your script works or can/must be adapted. (if I find time)
- Dom_CoteJan 28, 2026Iron Contributor
OK - forget it. 🤣
The bug mentioned here Microsoft Intune method of Secure Boot for Windows devices with IT-managed updates - Microsoft Support on Windows Pro (Business) devices is real. 🙄
All device in our test ring are stuck on the dreaded Intune error 65000 (unspecific licensing issue), none have attempted to update yet. (How come all our VMs are already updated? 🤔)Until Microsoft gets this to work on Pro devices, we'll have to wait.
Fun fact: Since the bug lies with Intune, no amount of local log or registry crunching will give you any hint at what's going on.
- Chris_CrampJan 29, 2026Brass Contributor
Dom_Cote
That's a +1 for me
Maybe I am luckier than you 2 out of the 54 client computers I have managed under Intune have Succeeded in the Secure Boot Certificate policy I created all the rest have the 65000 error. Let's hope Microsoft fixes this issue soon😔- Dom_CoteJan 29, 2026Iron Contributor
I'm not worried yet tbh. We still have a few months time. But yeah - it'd be great to get some clarity on when we can expect this to start working. Because there will always be a few stubborn devices that need manual attention, as we know.