With Windows 10 end of support behind us (October 14, 2025), TPM 2.0 queries have become one of the most common pre-migration health checks in enterprise IT. Whether you are running a Windows 11 eligibility audit, configuring Intune compliance policies, troubleshooting Autopilot attestation, or preparing for BitLocker deployment, this guide covers every method to query TPM status, version, and health via PowerShell — including fleet-wide approaches via Intune Remediation and SCCM.

Detail
Last UpdatedMarch 2026
Applies ToWindows 10, Windows 11, Windows Server 2019/2022/2025
Windows 11 RequirementTPM 2.0 (firmware or discrete), enabled and activated
Requires AdminGet-Tpm: Yes. tpmtool: No. CIM: No.
DifficultyBeginner

Method 1: Get-Tpm Cmdlet (Simplest)

The built-in Get-Tpm cmdlet from the TrustedPlatformModule module is the quickest way to check TPM status. It requires an elevated PowerShell session (Run as Administrator):

# Basic TPM status — requires elevation
Get-Tpm

Sample output on a healthy Windows 11 device:

TpmPresent            : True
TpmReady              : True
TpmEnabled            : True
TpmActivated          : True
TpmOwned              : True
RestartPending        : False
ManufacturerIdTxt     : INTC
ManufacturerVersion   : 302.12.0.0
ManufacturerVersionFull20 : 302.12.0.0
ManagedAuthLevel      : Full
OwnerAuth             : 
OwnerClearDisabled    : True
AutoProvisioning      : Enabled
LockedOut             : False
LockoutHealTime       : 10 minutes
CurrentPcrBanks       : {Sha1, Sha256}
AvailablePcrBanks     : {Sha1, Sha256}
LockoutCount          : 0

For Windows 11 eligibility, the critical properties are TpmPresent, TpmEnabled, TpmActivated, and TpmReady — all four must be True. TpmReady specifically indicates the TPM is fully provisioned and ready for use by the OS.

Method 2: Get TPM Version via CIM (No Elevation Required)

For scripts that run without elevation — such as Intune Remediation detection scripts running as user context — use the CIM-based approach:

# Get TPM version via CIM — no elevation required
$tpm = Get-CimInstance -Namespace "root\cimv2\Security\MicrosoftTpm" -ClassName "Win32_Tpm"

if ($tpm) {
    # SpecVersion returns e.g. "2.0, 1.16, 8" — take the highest version number
    $specVersion = ($tpm.SpecVersion -split ", " | Sort-Object | Select-Object -Last 1)

    [PSCustomObject]@{
        TPMPresent          = $true
        SpecVersion         = $specVersion
        ManufacturerVersion = $tpm.ManufacturerVersion
        IsEnabled           = $tpm.IsEnabled_InitialValue
        IsActivated         = $tpm.IsActivated_InitialValue
        IsOwned             = $tpm.IsOwned_InitialValue
    }
} else {
    Write-Host "No TPM found — device may not have a TPM or it is disabled in BIOS."
}

Method 3: tpmtool — Detailed Info Without Elevation

tpmtool.exe is a built-in Windows command-line tool that returns detailed TPM diagnostics including attestation readiness — useful for Autopilot troubleshooting. It does not require elevation:

# Full TPM device information
tpmtool getdeviceinformation

# Collect full TPM logs to a folder (useful for support escalation)
tpmtool gatherlogs "$env:USERPROFILE\Desktop\TPMLogs"

The getdeviceinformation output includes fields that Get-Tpm does not expose — notably Ready For Attestation, Is Capable For Attestation, and TPM Has Vulnerable Firmware. Parse it into a PowerShell object:

# Parse tpmtool output into a structured PowerShell object
$tpmToolOutput = tpmtool getdeviceinformation
$tpmInfo = @{}

foreach ($line in $tpmToolOutput) {
    if ($line -match "^-(.+?):\s+(.+)$") {
        $key   = $matches[1].Trim() -replace " ", "_"
        $value = $matches[2].Trim()
        $tpmInfo[$key] = $value
    }
}

[PSCustomObject]$tpmInfo | Format-List

Complete TPM Health Report

A combined script that pulls data from both Get-Tpm and CIM — useful as a single-device health check or the basis for a fleet audit:

# Comprehensive TPM health report
# Requires elevation for Get-Tpm; CIM section works without elevation

function Get-TPMHealthReport {
    $report = [ordered]@{ ComputerName = $env:COMPUTERNAME }

    # CIM section — no elevation needed
    try {
        $cimTpm = Get-CimInstance -Namespace "root\cimv2\Security\MicrosoftTpm" `
            -ClassName "Win32_Tpm" -ErrorAction Stop

        $specVersion = ($cimTpm.SpecVersion -split ", " |
            Sort-Object | Select-Object -Last 1)

        $report["TPM_Present"]             = $true
        $report["TPM_SpecVersion"]         = $specVersion
        $report["TPM_Is2_0"]              = ($specVersion -ge "2.0")
        $report["TPM_ManufacturerVersion"] = $cimTpm.ManufacturerVersion
        $report["TPM_Enabled"]             = $cimTpm.IsEnabled_InitialValue
        $report["TPM_Activated"]           = $cimTpm.IsActivated_InitialValue
        $report["TPM_Owned"]               = $cimTpm.IsOwned_InitialValue
    } catch {
        $report["TPM_Present"]   = $false
        $report["TPM_SpecVersion"] = "Not found"
    }

    # Get-Tpm section — requires elevation
    try {
        $getTpm = Get-Tpm -ErrorAction Stop
        $report["TPM_Ready"]            = $getTpm.TpmReady
        $report["TPM_LockedOut"]        = $getTpm.LockedOut
        $report["TPM_AutoProvisioning"] = $getTpm.AutoProvisioning
        $report["TPM_ManufacturerId"]   = $getTpm.ManufacturerIdTxt
        $report["PCR_Banks"]            = ($getTpm.CurrentPcrBanks -join ", ")
    } catch {
        $report["TPM_Ready"] = "Elevation required"
    }

    # Secure Boot status
    try {
        $report["SecureBoot_Enabled"] = (Confirm-SecureBootUEFI -ErrorAction Stop)
    } catch {
        $report["SecureBoot_Enabled"] = "Not supported or legacy BIOS"
    }

    # Windows 11 eligibility summary
    $w11Eligible = ($report["TPM_Is2_0"] -eq $true) -and
                   ($report["TPM_Enabled"] -eq $true) -and
                   ($report["TPM_Activated"] -eq $true)
    $report["Windows11_TPM_Eligible"] = $w11Eligible

    [PSCustomObject]$report
}

Get-TPMHealthReport | Format-List

Fleet Audit: Windows 11 TPM Eligibility via Intune Remediation

Use this as a detection-only Intune Remediation to identify devices in your fleet that do not meet the Windows 11 TPM requirement. The results appear in the Intune Remediations reporting dashboard:

# Detection script: Is device TPM 2.0 eligible for Windows 11?
# Deploy as detection-only Intune Remediation (no remediation script needed)
# Exit 0 = compliant (TPM 2.0 present and enabled)
# Exit 1 = non-compliant (TPM missing, disabled, or version 1.2)

try {
    $tpm = Get-CimInstance -Namespace "root\cimv2\Security\MicrosoftTpm" `
        -ClassName "Win32_Tpm" -ErrorAction Stop

    if (-not $tpm) {
        Write-Host "Non-compliant: No TPM found"
        exit 1
    }

    $specVersion = ($tpm.SpecVersion -split ", " | Sort-Object | Select-Object -Last 1)

    if ([version]$specVersion -lt [version]"2.0") {
        Write-Host "Non-compliant: TPM version $specVersion — Windows 11 requires 2.0"
        exit 1
    }

    if (-not $tpm.IsEnabled_InitialValue) {
        Write-Host "Non-compliant: TPM $specVersion present but disabled in BIOS"
        exit 1
    }

    if (-not $tpm.IsActivated_InitialValue) {
        Write-Host "Non-compliant: TPM $specVersion present but not activated"
        exit 1
    }

    Write-Host "Compliant: TPM $specVersion — enabled and activated"
    exit 0

} catch {
    Write-Host "Error querying TPM: $_"
    exit 1
}

Bulk Fleet Query via Invoke-Command

Query TPM status across multiple remote devices in parallel using PSRemoting:

# Query TPM status across multiple remote machines
$computers = @("PC001", "PC002", "PC003", "SERVER01")

$results = Invoke-Command -ComputerName $computers -ScriptBlock {
    $tpm = Get-CimInstance -Namespace "root\cimv2\Security\MicrosoftTpm" `
        -ClassName "Win32_Tpm" -ErrorAction SilentlyContinue

    if (-not $tpm) {
        return [PSCustomObject]@{
            Computer   = $env:COMPUTERNAME
            TPMPresent = $false
            Version    = "None"
            Enabled    = $false
            W11Ready   = $false
        }
    }

    $version = ($tpm.SpecVersion -split ", " | Sort-Object | Select-Object -Last 1)

    [PSCustomObject]@{
        Computer   = $env:COMPUTERNAME
        TPMPresent = $true
        Version    = $version
        Enabled    = $tpm.IsEnabled_InitialValue
        Activated  = $tpm.IsActivated_InitialValue
        W11Ready   = ($version -ge "2.0" -and $tpm.IsEnabled_InitialValue)
    }
} -ErrorAction SilentlyContinue

$results | Sort-Object W11Ready, Computer |
    Select-Object Computer, TPMPresent, Version, Enabled, Activated, W11Ready |
    Format-Table -AutoSize

# Export to CSV for management reporting
$results | Export-Csv "C:\Temp\TPM_Fleet_Audit.csv" -NoTypeInformation
Write-Host "Exported to C:\Temp\TPM_Fleet_Audit.csv"

Check TPM Attestation Readiness (Autopilot / Windows Hello for Business)

For Autopilot deployments and Windows Hello for Business, the TPM must not only be present and enabled but also attestation-capable. Virtual TPMs and some older discrete TPMs are blocked from attestation by Microsoft:

# Check TPM attestation readiness
$tpmTool = tpmtool getdeviceinformation

$attestReady    = ($tpmTool | Select-String "Ready For Attestation").ToString() -match "True"
$attestCapable  = ($tpmTool | Select-String "Is Capable For Attestation").ToString() -match "True"
$vulnFirmware   = ($tpmTool | Select-String "TPM Has Vulnerable Firmware").ToString() -match "True"
$clearNeeded    = ($tpmTool | Select-String "Clear Needed To Recover").ToString() -match "True"

[PSCustomObject]@{
    ComputerName         = $env:COMPUTERNAME
    ReadyForAttestation  = $attestReady
    CapableForAttestation = $attestCapable
    VulnerableFirmware   = $vulnFirmware
    ClearNeededToRecover = $clearNeeded
    AttestationStatus    = if ($attestReady) { "OK" }
                           elseif (-not $attestCapable) { "Not capable — virtual TPM or blocklisted" }
                           elseif ($vulnFirmware) { "Blocked — vulnerable firmware" }
                           elseif ($clearNeeded) { "TPM clear required" }
                           else { "Not ready — check tpmtool output" }
} | Format-List

Common TPM Issues and Fixes

IssueCauseFix
TpmPresent = FalseTPM disabled in BIOS/UEFIEnable TPM in BIOS — look for Intel PTT, AMD fTPM, or dedicated TPM setting
TpmReady = False but TpmPresent = TrueTPM not provisioned or ownedRun: Initialize-Tpm -AllowClear — or clear TPM in BIOS and let Windows reprovision
TPM version 1.2 on deviceOlder hardware without firmware TPM 2.0Check BIOS for firmware upgrade; some older Intel devices can update from PTT 1.2 to 2.0
Ready For Attestation: FalseVirtual TPM, vulnerable firmware, or blocklisted chipVirtual TPMs cannot attest. For vulnerable firmware, update TPM firmware from the OEM
TPM LockedOut = TrueToo many failed authorization attemptsWait for lockout to heal (shown in LockoutHealTime); or clear TPM in BIOS
Get-Tpm returns error 0x80280400TPM Base Services not runningStart service: Start-Service -Name “TPM Base Services”

Summary

TPM querying in PowerShell is more relevant in 2026 than ever — Windows 11 eligibility audits, Autopilot attestation troubleshooting, and BitLocker compliance checks all depend on accurate TPM status data. Use the CIM method for non-elevated or Intune Remediation contexts, Get-Tpm for elevated single-device checks, and tpmtool for attestation diagnostics.

  • Use Get-CimInstance -Namespace "root\cimv2\Security\MicrosoftTpm" -ClassName "Win32_Tpm" for non-elevated scripts and fleet audits
  • Use Get-Tpm (elevated) for full status including TpmReady, lockout state, and PCR banks
  • Use tpmtool getdeviceinformation for attestation readiness — essential for Autopilot and Windows Hello for Business troubleshooting
  • Deploy the Intune Remediation detection script as a fleet audit to identify Windows 11-ineligible devices before migrating
  • Virtual TPMs (Hyper-V, Azure VMs) cannot attest — this is by design and not fixable