<#
Checks:
- TPM presence & readiness
- Secure Boot status (with fallbacks)
- OS version / build and a simple feature-branch hint
Run as Administrator.
#>
[CmdletBinding()
param()
]function Test-IsAdministrator
try {
$current = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($current)
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
} catch { return $false }
}
{if (-not (Test-IsAdministrator))
Write-Error "Please run this script in an elevated PowerShell (Run as administrator)."
exit 1
}
{# --- OS details --
try {
$osCim = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop
$regOS = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -ErrorAction SilentlyContinue
$build = int
$ubr = int
$disp = $regOS.DisplayVersion
$osInfo = [PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
OS_Caption = $osCim.Caption
OS_Version = $osCim.Version
OS_Build = if ($ubr) { "$build.$ubr" } else { "$build" }
DisplayVersion = $disp
}
} catch {
Write-Warning "Unable to read OS details: $($_.Exception.Message)"
$osInfo = $null
}
-# Feature branch hin
function Get-FeatureBranchHint {
param([int]$Build)
switch ($Build) {
{ $_ -ge 26100 } { "Windows 11 24H2 (26100+)" ; break }
{ $_ -ge 22635 } { "Windows 11 23H2 (2263x family)" ; break }
{ $_ -ge 22621 } { "Windows 11 22H2/23H2 family (22621/22631)" ; break }
{ $_ -ge 19045 } { "Windows 10 22H2 (19045)" ; break }
default { "Older/Unmapped build" }
}
}
$featureHint = if ($regOS.CurrentBuild) { Get-FeatureBranchHint -Build $regOS.CurrentBuild } else { $null }
t# --- Firmware type (UEFI vs BIOS) --
$firmwareTypeValue = $null
try {
$firmwareTypeValue = (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control" -Name PEFirmwareType -ErrorAction Stop).PEFirmwareType
} catch {}
$firmwareType = switch ($firmwareTypeValue) { 2 { "UEFI" } 1 { "BIOS" } default { "Unknown" } }
-# --- Secure Boot status --
$secureBootEnabled = $null
$secureBootMethod = $null
try {
$secureBootEnabled = Confirm-SecureBootUEFI -ErrorAction Stop
$secureBootMethod = "Confirm-SecureBootUEFI"
} catch {
try {
$sb = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State" -ErrorAction Stop
$secureBootEnabled = [bool]$sb.UEFISecureBootEnabled
$secureBootMethod = "Registry (State\UEFISecureBootEnabled)"
} catch {
try {
$sbCim = Get-CimInstance -Namespace root\wmi -Class MS_SecureBoot -ErrorAction Stop
$secureBootEnabled = [bool]$sbCim.SecureBootEnabled
$secureBootMethod = "CIM: MS_SecureBoot"
} catch {
$secureBootEnabled = $null
$secureBootMethod = "Unknown"
}
}
}
-# --- TPM status --
$tpmPresent = $false
$tpmReady = $false
$tpmSpec = $null
$tpmManuf = $null
$tpmMethod = $null
-try
$tpm = Get-Tpm -ErrorAction Stop
if ($null -ne $tpm) {
$tpmPresent = [bool]$tpm.TpmPresent
$tpmReady = [bool]$tpm.TpmReady
$tpmSpec = $tpm.SpecVersion
$tpmManuf = $tpm.ManufacturerIdTxt
$tpmMethod = "Get-Tpm"
}
} catch {
try {
$tpmWmi = Get-WmiObject -Namespace "root\CIMV2\Security\MicrosoftTpm" -Class Win32_Tpm -ErrorAction Stop
if ($tpmWmi) {
$tpmPresent = $true
$tpmReady = [bool]$tpmWmi.IsEnabled_InitialValue
$tpmSpec = $tpmWmi.SpecVersion
$tpmManuf = $tpmWmi.ManufacturerId
$tpmMethod = "WMI: Win32_Tpm"
}
} catch {
$tpmMethod = "Unknown"
}
}
{# --- Result object --
$result = [PSCustomObject]@{
ComputerName = $osInfo.ComputerName
FirmwareType = $firmwareType
SecureBootEnabled = $secureBootEnabled
SecureBootMethod = $secureBootMethod
TpmPresent = $tpmPresent
TpmReady = $tpmReady
TpmSpecVersion = $tpmSpec
TpmManufacturer = $tpmManuf
OS_Caption = $osInfo.OS_Caption
OS_Version = $osInfo.OS_Version
OS_Build = $osInfo.OS_Build
DisplayVersion = $osInfo.DisplayVersion
FeatureBranchHint = $featureHint
}
-# --- Readiness summary --
$missing = @()
if ($firmwareType -ne "UEFI") { $missing += "UEFI firmware" }
if (-not $secureBootEnabled) { $missing += "Secure Boot" }
if (-not $tpmPresent) { $missing += "TPM 2.0" }
elseif (-not $tpmReady) { $missing += "TPM not ready (initialize in firmware)" }
-$ready = ($missing.Count -eq 0
)Write-Host "=== Windows 11 Readiness (incl. 24H2) ===" -ForegroundColor Cya
if ($ready) {
Write-Host "Status: READY" -ForegroundColor Green
} else {
Write-Host "Status: NOT READY" -ForegroundColor Red
if ($missing.Count -gt 0) {
Write-Host "Missing: $($missing -join ', ')" -ForegroundColor Yellow
}
}
Write-Host ""
$result | Format-List
n# Exit code for automation: 0 when ready, 2 when not read
if ($ready) { exit 0 } else { exit 2 }