Public/Get-HardwareReadinessJSON.ps1
function Get-HardwareReadinessJSON { <# .SYNOPSIS Returns raw JSON results of Windows 11 hardware compatibility check. .DESCRIPTION Performs detailed hardware compatibility checks for Windows 11 requirements including TPM, SecureBoot, CPU, Memory, and Storage requirements. Returns results in JSON format. .EXAMPLE Get-HardwareReadinessJSON Returns JSON string containing detailed hardware check results. #> [CmdletBinding()] param() # Constants [int]$MinOSDiskSizeGB = 64 [int]$MinMemoryGB = 4 [Uint32]$MinClockSpeedMHz = 1000 [Uint32]$MinLogicalCores = 2 [Uint16]$RequiredAddressWidth = 64 $PASS_STRING = "PASS" $FAIL_STRING = "FAIL" $FAILED_TO_RUN_STRING = "FAILED TO RUN" $UNDETERMINED_CAPS_STRING = "UNDETERMINED" $UNDETERMINED_STRING = "Undetermined" $CAPABLE_STRING = "Capable" $NOT_CAPABLE_STRING = "Not capable" $CAPABLE_CAPS_STRING = "CAPABLE" $NOT_CAPABLE_CAPS_STRING = "NOT CAPABLE" $STORAGE_STRING = "Storage" $OS_DISK_SIZE_STRING = "OSDiskSize" $MEMORY_STRING = "Memory" $SYSTEM_MEMORY_STRING = "System_Memory" $GB_UNIT_STRING = "GB" $TPM_STRING = "TPM" $TPM_VERSION_STRING = "TPMVersion" $PROCESSOR_STRING = "Processor" $SECUREBOOT_STRING = "SecureBoot" $I7_7820HQ_CPU_STRING = "i7-7820hq CPU" # Log format strings $logFormat = '{0}: {1}={2}. {3}; ' $logFormatWithUnit = '{0}: {1}={2}{3}. {4}; ' $logFormatReturnReason = '{0}, ' $logFormatException = '{0}; ' $logFormatWithBlob = '{0}: {1}. {2}; ' # Reset output object $script:outObject = @{ returnCode = -2 returnResult = $FAILED_TO_RUN_STRING returnReason = "" logging = "" } try { # Check Storage $osDrive = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceID='$($env:SystemDrive)'" $osDriveSize = [math]::Round($osDrive.Size / 1GB) if ($osDriveSize -ge $MinOSDiskSizeGB) { $script:outObject.logging += $logFormatWithUnit -f $STORAGE_STRING, $OS_DISK_SIZE_STRING, $osDriveSize, $GB_UNIT_STRING, $PASS_STRING UpdateReturnCode 0 } else { $script:outObject.logging += $logFormatWithUnit -f $STORAGE_STRING, $OS_DISK_SIZE_STRING, $osDriveSize, $GB_UNIT_STRING, $FAIL_STRING $script:outObject.returnReason += $logFormatReturnReason -f "Insufficient disk space" UpdateReturnCode 1 } # Check Memory $memory = Get-CimInstance -ClassName Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum $memoryGB = [math]::Round($memory.Sum / 1GB) if ($memoryGB -ge $MinMemoryGB) { $script:outObject.logging += $logFormatWithUnit -f $MEMORY_STRING, $SYSTEM_MEMORY_STRING, $memoryGB, $GB_UNIT_STRING, $PASS_STRING UpdateReturnCode 0 } else { $script:outObject.logging += $logFormatWithUnit -f $MEMORY_STRING, $SYSTEM_MEMORY_STRING, $memoryGB, $GB_UNIT_STRING, $FAIL_STRING $script:outObject.returnReason += $logFormatReturnReason -f "Insufficient memory" UpdateReturnCode 1 } # Check TPM try { $tpm = Get-Tpm if ($null -eq $tpm) { UpdateReturnCode -ReturnCode 1 $script:outObject.returnReason += $logFormatReturnReason -f $TPM_STRING $script:outObject.logging += $logFormatWithBlob -f $TPM_STRING, "TPM is null", $FAIL_STRING } elseif ($tpm.TpmPresent) { $tpmVersion = Get-WmiObject -Class Win32_Tpm -Namespace root\CIMV2\Security\MicrosoftTpm | Select-Object -Property SpecVersion if ($null -eq $tpmVersion.SpecVersion) { UpdateReturnCode -ReturnCode 1 $script:outObject.returnReason += $logFormatReturnReason -f $TPM_STRING $script:outObject.logging += $logFormat -f $TPM_STRING, $TPM_VERSION_STRING, "null", $FAIL_STRING } $majorVersion = $tpmVersion.SpecVersion.Split(",")[0] -as [int] if ($majorVersion -lt 2) { UpdateReturnCode -ReturnCode 1 $script:outObject.returnReason += $logFormatReturnReason -f $TPM_STRING $script:outObject.logging += $logFormat -f $TPM_STRING, $TPM_VERSION_STRING, ($tpmVersion.SpecVersion), $FAIL_STRING } else { $script:outObject.logging += $logFormat -f $TPM_STRING, $TPM_VERSION_STRING, ($tpmVersion.SpecVersion), $PASS_STRING UpdateReturnCode -ReturnCode 0 } } else { if ($tpm.GetType().Name -eq "String") { UpdateReturnCode -ReturnCode -1 $script:outObject.logging += $logFormat -f $TPM_STRING, $TPM_VERSION_STRING, $UNDETERMINED_STRING, $UNDETERMINED_CAPS_STRING $script:outObject.logging += $logFormatException -f $tpm } else { UpdateReturnCode -ReturnCode 1 $script:outObject.returnReason += $logFormatReturnReason -f $TPM_STRING $script:outObject.logging += $logFormat -f $TPM_STRING, $TPM_VERSION_STRING, ($tpm.TpmPresent), $FAIL_STRING } } } catch { UpdateReturnCode -ReturnCode -1 $script:outObject.logging += $logFormat -f $TPM_STRING, $TPM_VERSION_STRING, $UNDETERMINED_STRING, $UNDETERMINED_CAPS_STRING $script:outObject.logging += $logFormatException -f "$($_.Exception.GetType().Name) $($_.Exception.Message)" } # Check Processor $processor = Get-CimInstance -ClassName Win32_Processor $cpuCheck = [CpuFamily]::Validate($processor.Manufacturer, $processor.Architecture) $cpuDetailsLog = "{AddressWidth=$($processor.AddressWidth); MaxClockSpeed=$($processor.MaxClockSpeed); NumberOfLogicalCores=$($processor.NumberOfLogicalProcessors); Manufacturer=$($processor.Manufacturer); Caption=$($processor.Caption); $($cpuCheck.Message)}" if ($cpuCheck.IsValid -and $processor.AddressWidth -eq $RequiredAddressWidth -and $processor.NumberOfCores -ge $MinLogicalCores -and $processor.MaxClockSpeed -ge $MinClockSpeedMHz) { $script:outObject.logging += $logFormatWithBlob -f $PROCESSOR_STRING, $cpuDetailsLog, $PASS_STRING UpdateReturnCode 0 } else { $script:outObject.logging += $logFormatWithBlob -f $PROCESSOR_STRING, $cpuDetailsLog, $FAIL_STRING $script:outObject.returnReason += $logFormatReturnReason -f "Processor not compatible" UpdateReturnCode 1 } # Check SecureBoot try { $secureBoot = Confirm-SecureBootUEFI if ($secureBoot) { $script:outObject.logging += $logFormatWithBlob -f $SECUREBOOT_STRING, "Enabled", $PASS_STRING UpdateReturnCode 0 } else { $script:outObject.logging += $logFormatWithBlob -f $SECUREBOOT_STRING, "Disabled", $FAIL_STRING $script:outObject.returnReason += $logFormatReturnReason -f "SecureBoot disabled" UpdateReturnCode 1 } } catch { $script:outObject.logging += $logFormatWithBlob -f $SECUREBOOT_STRING, "Error", $FAILED_TO_RUN_STRING $script:outObject.returnReason += $logFormatException -f $_.Exception.Message UpdateReturnCode -1 } # Set final result if ($script:outObject.returnCode -eq 0) { $script:outObject.returnResult = $CAPABLE_CAPS_STRING } elseif ($script:outObject.returnCode -eq 1) { $script:outObject.returnResult = $NOT_CAPABLE_CAPS_STRING } else { $script:outObject.returnResult = $FAILED_TO_RUN_STRING } } catch { $script:outObject.returnReason = $_.Exception.Message $script:outObject.returnCode = -1 $script:outObject.returnResult = $FAILED_TO_RUN_STRING } # Return JSON result $script:outObject | ConvertTo-Json -Compress } |