Back to Resources
Level
Script
Patching
Manually verifying each component required for Windows 11—such as disk space, memory, TPM version, and CPU capabilities—can be both time-consuming and prone to human error. This script streamlines that process by automatically detecting and reporting hardware readiness, helping IT teams and MSPs quickly identify machines suitable for Windows 11 upgrades.
This script checks critical Windows 11 eligibility parameters, including available storage, system memory, TPM presence and version, processor architecture, and Secure Boot availability. It provides clear pass/fail feedback for each requirement, then consolidates the results into an overall readiness status, allowing you to see at a glance if a system can safely upgrade.
If any check fails, the script calls attention to that failure so you can investigate or remediate the issue. It also identifies indeterminate factors when certain details can't be retrieved, making troubleshooting straightforward.
1<#
2This resource is provided as a convenience for Level users. We cannot
3guarantee it will work in all environments. Please test before deploying
4to your production environment. We welcome contributions to our community
5library
6
7Level Library
8https://level.io/library/script-windows-11-upgrade-hardware-check
9#>
10$exitCode = 0
11
12[int]$MinOSDiskSizeGB = 64
13[int]$MinMemoryGB = 4
14[Uint32]$MinClockSpeedMHz = 1000
15[Uint32]$MinLogicalCores = 2
16[Uint16]$RequiredAddressWidth = 64
17
18$PASS_STRING = "PASS"
19$FAIL_STRING = "FAIL"
20$FAILED_TO_RUN_STRING = "FAILED TO RUN"
21$UNDETERMINED_CAPS_STRING = "UNDETERMINED"
22$UNDETERMINED_STRING = "Undetermined"
23$CAPABLE_STRING = "Capable"
24$NOT_CAPABLE_STRING = "Not capable"
25$CAPABLE_CAPS_STRING = "CAPABLE"
26$NOT_CAPABLE_CAPS_STRING = "NOT CAPABLE"
27$STORAGE_STRING = "Storage"
28$OS_DISK_SIZE_STRING = "OSDiskSize"
29$MEMORY_STRING = "Memory"
30$SYSTEM_MEMORY_STRING = "System_Memory"
31$GB_UNIT_STRING = "GB"
32$TPM_STRING = "TPM"
33$TPM_VERSION_STRING = "TPMVersion"
34$PROCESSOR_STRING = "Processor"
35$SECUREBOOT_STRING = "SecureBoot"
36$I7_7820HQ_CPU_STRING = "i7-7820hq CPU"
37
38# Function for colored console output
39function Write-Color {
40 param(
41 [string]$Message,
42 [string]$Color
43 )
44 $colorHash = @{
45 'Red' = [ConsoleColor]::Red
46 'Green' = [ConsoleColor]::Green
47 'Yellow' = [ConsoleColor]::Yellow
48 }
49
50 Write-Host $Message -ForegroundColor $colorHash[$Color]
51}
52
53# Function to print results to console with colors
54function Print-CheckResult {
55 param(
56 [string]$CheckName,
57 [string]$Status,
58 [string]$Details
59 )
60 switch ($Status) {
61 "PASS" { Write-Color "$($CheckName): $($Status); $($Details)" "Green" }
62 "FAIL" { Write-Color "$($CheckName): $($Status); $($Details)" "Red" }
63 default { Write-Color "$($CheckName): $($Status); $($Details)" "Yellow" }
64 }
65}
66
67# return returnCode is -1 when an exception is thrown. 1 if the value does not meet requirements. 0 if successful. -2 default, script didn't run.
68$outObject = @{ returnCode = -2; returnResult = $FAILED_TO_RUN_STRING; returnReason = ""; logging = "" }
69
70# NOT CAPABLE(1) state takes precedence over UNDETERMINED(-1) state
71function Private:UpdateReturnCode {
72 param(
73 [Parameter(Mandatory = $true)]
74 [ValidateRange(-2, 1)]
75 [int] $ReturnCode
76 )
77
78 Switch ($ReturnCode) {
79 0 {
80 if ($outObject.returnCode -eq -2) {
81 $outObject.returnCode = $ReturnCode
82 }
83 }
84 1 {
85 $outObject.returnCode = $ReturnCode
86 }
87 -1 {
88 if ($outObject.returnCode -ne 1) {
89 $outObject.returnCode = $ReturnCode
90 }
91 }
92 }
93}
94
95$Source = @"
96using Microsoft.Win32;
97using System;
98using System.Runtime.InteropServices;
99
100public class CpuFamilyResult
101{
102 public bool IsValid { get; set; }
103 public string Message { get; set; }
104}
105
106public class CpuFamily
107{
108 [StructLayout(LayoutKind.Sequential)]
109 public struct SYSTEM_INFO
110 {
111 public ushort ProcessorArchitecture;
112 ushort Reserved;
113 public uint PageSize;
114 public IntPtr MinimumApplicationAddress;
115 public IntPtr MaximumApplicationAddress;
116 public IntPtr ActiveProcessorMask;
117 public uint NumberOfProcessors;
118 public uint ProcessorType;
119 public uint AllocationGranularity;
120 public ushort ProcessorLevel;
121 public ushort ProcessorRevision;
122 }
123
124 [DllImport("kernel32.dll")]
125 internal static extern void GetNativeSystemInfo(ref SYSTEM_INFO lpSystemInfo);
126
127 public enum ProcessorFeature : uint
128 {
129 ARM_SUPPORTED_INSTRUCTIONS = 34
130 }
131
132 [DllImport("kernel32.dll")]
133 [return: MarshalAs(UnmanagedType.Bool)]
134 static extern bool IsProcessorFeaturePresent(ProcessorFeature processorFeature);
135
136 private const ushort PROCESSOR_ARCHITECTURE_X86 = 0;
137 private const ushort PROCESSOR_ARCHITECTURE_ARM64 = 12;
138 private const ushort PROCESSOR_ARCHITECTURE_X64 = 9;
139
140 private const string INTEL_MANUFACTURER = "GenuineIntel";
141 private const string AMD_MANUFACTURER = "AuthenticAMD";
142 private const string QUALCOMM_MANUFACTURER = "Qualcomm Technologies Inc";
143
144 public static CpuFamilyResult Validate(string manufacturer, ushort processorArchitecture)
145 {
146 CpuFamilyResult cpuFamilyResult = new CpuFamilyResult();
147
148 if (string.IsNullOrWhiteSpace(manufacturer))
149 {
150 cpuFamilyResult.IsValid = false;
151 cpuFamilyResult.Message = "Manufacturer is null or empty";
152 return cpuFamilyResult;
153 }
154
155 string registryPath = "HKEY_LOCAL_MACHINE\\Hardware\\Description\\System\\CentralProcessor\\0";
156 SYSTEM_INFO sysInfo = new SYSTEM_INFO();
157 GetNativeSystemInfo(ref sysInfo);
158
159 switch (processorArchitecture)
160 {
161 case PROCESSOR_ARCHITECTURE_ARM64:
162
163 if (manufacturer.Equals(QUALCOMM_MANUFACTURER, StringComparison.OrdinalIgnoreCase))
164 {
165 bool isArmv81Supported = IsProcessorFeaturePresent(ProcessorFeature.ARM_SUPPORTED_INSTRUCTIONS);
166
167 if (!isArmv81Supported)
168 {
169 string registryName = "CP 4030";
170 long registryValue = (long)Registry.GetValue(registryPath, registryName, -1);
171 long atomicResult = (registryValue >> 20) & 0xF;
172
173 if (atomicResult >= 2)
174 {
175 isArmv81Supported = true;
176 }
177 }
178
179 cpuFamilyResult.IsValid = isArmv81Supported;
180 cpuFamilyResult.Message = isArmv81Supported ? "" : "Processor does not implement ARM v8.1 atomic instruction";
181 }
182 else
183 {
184 cpuFamilyResult.IsValid = false;
185 cpuFamilyResult.Message = "The processor isn't currently supported for Windows 11";
186 }
187
188 break;
189
190 case PROCESSOR_ARCHITECTURE_X64:
191 case PROCESSOR_ARCHITECTURE_X86:
192
193 int cpuFamily = sysInfo.ProcessorLevel;
194 int cpuModel = (sysInfo.ProcessorRevision >> 8) & 0xFF;
195 int cpuStepping = sysInfo.ProcessorRevision & 0xFF;
196
197 if (manufacturer.Equals(INTEL_MANUFACTURER, StringComparison.OrdinalIgnoreCase))
198 {
199 try
200 {
201 cpuFamilyResult.IsValid = true;
202 cpuFamilyResult.Message = "";
203
204 if (cpuFamily >= 6 && cpuModel <= 95 && !(cpuFamily == 6 && cpuModel == 85))
205 {
206 cpuFamilyResult.IsValid = false;
207 cpuFamilyResult.Message = "";
208 }
209 else if (cpuFamily == 6 && (cpuModel == 142 || cpuModel == 158) && cpuStepping == 9)
210 {
211 string registryName = "Platform Specific Field 1";
212 int registryValue = (int)Registry.GetValue(registryPath, registryName, -1);
213
214 if ((cpuModel == 142 && registryValue != 16) || (cpuModel == 158 && registryValue != 8))
215 {
216 cpuFamilyResult.IsValid = false;
217 }
218 cpuFamilyResult.Message = "PlatformId " + registryValue;
219 }
220 }
221 catch (Exception ex)
222 {
223 cpuFamilyResult.IsValid = false;
224 cpuFamilyResult.Message = "Exception:" + ex.GetType().Name;
225 }
226 }
227 else if (manufacturer.Equals(AMD_MANUFACTURER, StringComparison.OrdinalIgnoreCase))
228 {
229 cpuFamilyResult.IsValid = true;
230 cpuFamilyResult.Message = "";
231
232 if (cpuFamily < 23 || (cpuFamily == 23 && (cpuModel == 1 || cpuModel == 17)))
233 {
234 cpuFamilyResult.IsValid = false;
235 }
236 }
237 else
238 {
239 cpuFamilyResult.IsValid = false;
240 cpuFamilyResult.Message = "Unsupported Manufacturer: " + manufacturer + ", Architecture: " + processorArchitecture + ", CPUFamily: " + sysInfo.ProcessorLevel + ", ProcessorRevision: " + sysInfo.ProcessorRevision;
241 }
242
243 break;
244
245 default:
246 cpuFamilyResult.IsValid = false;
247 cpuFamilyResult.Message = "Unsupported CPU category. Manufacturer: " + manufacturer + ", Architecture: " + processorArchitecture + ", CPUFamily: " + sysInfo.ProcessorLevel + ", ProcessorRevision: " + sysInfo.ProcessorRevision;
248 break;
249 }
250 return cpuFamilyResult;
251 }
252}
253"@
254
255# Storage
256try {
257 $osDrive = Get-WmiObject -Class Win32_OperatingSystem | Select-Object -Property SystemDrive
258 $osDriveSize = Get-WmiObject -Class Win32_LogicalDisk -filter "DeviceID='$($osDrive.SystemDrive)'" | Select-Object @{Name = "SizeGB"; Expression = { $_.Size / 1GB -as [int] } }
259
260 if ($null -eq $osDriveSize) {
261 UpdateReturnCode -ReturnCode 1
262 $outObject.returnReason += $logFormatReturnReason -f $STORAGE_STRING
263 $outObject.logging += $logFormatWithBlob -f $STORAGE_STRING, "Storage is null", $FAIL_STRING
264 Print-CheckResult $STORAGE_STRING $FAIL_STRING "Storage is null"
265 $exitCode = 1
266 }
267 elseif ($osDriveSize.SizeGB -lt $MinOSDiskSizeGB) {
268 UpdateReturnCode -ReturnCode 1
269 $outObject.returnReason += $logFormatReturnReason -f $STORAGE_STRING
270 $outObject.logging += $logFormatWithUnit -f $STORAGE_STRING, $OS_DISK_SIZE_STRING, ($osDriveSize.SizeGB), $GB_UNIT_STRING, $FAIL_STRING
271 Print-CheckResult $STORAGE_STRING $FAIL_STRING "OSDiskSize=$($osDriveSize.SizeGB)GB, Minimum Required=$MinOSDiskSizeGB GB"
272 $exitCode = 1
273 }
274 else {
275 $outObject.logging += $logFormatWithUnit -f $STORAGE_STRING, $OS_DISK_SIZE_STRING, ($osDriveSize.SizeGB), $GB_UNIT_STRING, $PASS_STRING
276 Print-CheckResult $STORAGE_STRING $PASS_STRING "OSDiskSize=$($osDriveSize.SizeGB)GB"
277 UpdateReturnCode -ReturnCode 0
278 }
279}
280catch {
281 UpdateReturnCode -ReturnCode -1
282 $outObject.logging += $logFormat -f $STORAGE_STRING, $OS_DISK_SIZE_STRING, $UNDETERMINED_STRING, $UNDETERMINED_CAPS_STRING
283 $outObject.logging += $logFormatException -f "$($_.Exception.GetType().Name) $($_.Exception.Message)"
284 Print-CheckResult $STORAGE_STRING $UNDETERMINED_CAPS_STRING "Exception: $($_.Exception.Message)"
285 $exitCode = 1
286}
287
288# Memory (bytes)
289try {
290 $memory = Get-WmiObject Win32_PhysicalMemory | Measure-Object -Property Capacity -Sum | Select-Object @{Name = "SizeGB"; Expression = { $_.Sum / 1GB -as [int] } }
291
292 if ($null -eq $memory) {
293 UpdateReturnCode -ReturnCode 1
294 $outObject.returnReason += $logFormatReturnReason -f $MEMORY_STRING
295 $outObject.logging += $logFormatWithBlob -f $MEMORY_STRING, "Memory is null", $FAIL_STRING
296 Print-CheckResult $MEMORY_STRING $FAIL_STRING "Memory is null"
297 $exitCode = 1
298 }
299 elseif ($memory.SizeGB -lt $MinMemoryGB) {
300 UpdateReturnCode -ReturnCode 1
301 $outObject.returnReason += $logFormatReturnReason -f $MEMORY_STRING
302 $outObject.logging += $logFormatWithUnit -f $MEMORY_STRING, $SYSTEM_MEMORY_STRING, ($memory.SizeGB), $GB_UNIT_STRING, $FAIL_STRING
303 Print-CheckResult $MEMORY_STRING $FAIL_STRING "SystemMemory=$($memory.SizeGB)GB, Minimum Required=$MinMemoryGB GB"
304 $exitCode = 1
305 }
306 else {
307 $outObject.logging += $logFormatWithUnit -f $MEMORY_STRING, $SYSTEM_MEMORY_STRING, ($memory.SizeGB), $GB_UNIT_STRING, $PASS_STRING
308 Print-CheckResult $MEMORY_STRING $PASS_STRING "SystemMemory=$($memory.SizeGB)GB"
309 UpdateReturnCode -ReturnCode 0
310 }
311}
312catch {
313 UpdateReturnCode -ReturnCode -1
314 $outObject.logging += $logFormat -f $MEMORY_STRING, $SYSTEM_MEMORY_STRING, $UNDETERMINED_STRING, $UNDETERMINED_CAPS_STRING
315 $outObject.logging += $logFormatException -f "$($_.Exception.GetType().Name) $($_.Exception.Message)"
316 Print-CheckResult $MEMORY_STRING $UNDETERMINED_CAPS_STRING "Exception: $($_.Exception.Message)"
317 $exitCode = 1
318}
319
320# TPM
321try {
322 $tpm = Get-Tpm
323
324 if ($null -eq $tpm) {
325 UpdateReturnCode -ReturnCode 1
326 $outObject.returnReason += $logFormatReturnReason -f $TPM_STRING
327 $outObject.logging += $logFormatWithBlob -f $TPM_STRING, "TPM is null", $FAIL_STRING
328 Print-CheckResult $TPM_STRING $FAIL_STRING "TPM is null"
329 $exitCode = 1
330 }
331 elseif ($tpm.TpmPresent) {
332 $tpmVersion = Get-WmiObject -Class Win32_Tpm -Namespace root\CIMV2\Security\MicrosoftTpm | Select-Object -Property SpecVersion
333
334 if ($null -eq $tpmVersion.SpecVersion) {
335 UpdateReturnCode -ReturnCode 1
336 $outObject.returnReason += $logFormatReturnReason -f $TPM_STRING
337 $outObject.logging += $logFormat -f $TPM_STRING, $TPM_VERSION_STRING, "null", $FAIL_STRING
338 Print-CheckResult $TPM_STRING $FAIL_STRING "TPMVersion=null"
339 $exitCode = 1
340 }
341
342 $majorVersion = $tpmVersion.SpecVersion.Split(",")[0] -as [int]
343 if ($majorVersion -lt 2) {
344 UpdateReturnCode -ReturnCode 1
345 $outObject.returnReason += $logFormatReturnReason -f $TPM_STRING
346 $outObject.logging += $logFormat -f $TPM_STRING, $TPM_VERSION_STRING, ($tpmVersion.SpecVersion), $FAIL_STRING
347 Print-CheckResult $TPM_STRING $FAIL_STRING "TPMVersion=$($tpmVersion.SpecVersion)"
348 $exitCode = 1
349 }
350 else {
351 $outObject.logging += $logFormat -f $TPM_STRING, $TPM_VERSION_STRING, ($tpmVersion.SpecVersion), $PASS_STRING
352 Print-CheckResult $TPM_STRING $PASS_STRING "TPMVersion=$($tpmVersion.SpecVersion)"
353 UpdateReturnCode -ReturnCode 0
354 }
355 }
356 else {
357 if ($tpm.GetType().Name -eq "String") {
358 UpdateReturnCode -ReturnCode -1
359 $outObject.logging += $logFormat -f $TPM_STRING, $TPM_VERSION_STRING, $UNDETERMINED_STRING, $UNDETERMINED_CAPS_STRING
360 $outObject.logging += $logFormatException -f $tpm
361 Print-CheckResult $TPM_STRING $UNDETERMINED_CAPS_STRING "TPM information undetermined"
362 }
363 else {
364 UpdateReturnCode -ReturnCode 1
365 $outObject.returnReason += $logFormatReturnReason -f $TPM_STRING
366 $outObject.logging += $logFormat -f $TPM_STRING, $TPM_VERSION_STRING, ($tpm.TpmPresent), $FAIL_STRING
367 Print-CheckResult $TPM_STRING $FAIL_STRING "TPM not present"
368 }
369 $exitCode = 1
370 }
371}
372catch {
373 UpdateReturnCode -ReturnCode -1
374 $outObject.logging += $logFormat -f $TPM_STRING, $TPM_VERSION_STRING, $UNDETERMINED_STRING, $UNDETERMINED_CAPS_STRING
375 $outObject.logging += $logFormatException -f "$($_.Exception.GetType().Name) $($_.Exception.Message)"
376 Print-CheckResult $TPM_STRING $UNDETERMINED_CAPS_STRING "Exception: $($_.Exception.Message)"
377 $exitCode = 1
378}
379
380# CPU Details
381$cpuDetails;
382try {
383 $cpuDetails = @(Get-WmiObject -Class Win32_Processor)[0]
384
385 if ($null -eq $cpuDetails) {
386 UpdateReturnCode -ReturnCode 1
387 $exitCode = 1
388 $outObject.returnReason += $logFormatReturnReason -f $PROCESSOR_STRING
389 $outObject.logging += $logFormatWithBlob -f $PROCESSOR_STRING, "CpuDetails is null", $FAIL_STRING
390 Print-CheckResult $PROCESSOR_STRING $FAIL_STRING "CpuDetails is null"
391 }
392 else {
393 $processorCheckFailed = $false
394
395 # AddressWidth
396 if ($null -eq $cpuDetails.AddressWidth -or $cpuDetails.AddressWidth -ne $RequiredAddressWidth) {
397 UpdateReturnCode -ReturnCode 1
398 $processorCheckFailed = $true
399 Print-CheckResult $PROCESSOR_STRING $FAIL_STRING "AddressWidth=$($cpuDetails.AddressWidth), Required=$RequiredAddressWidth"
400 $exitCode = 1
401 }
402
403 # ClockSpeed is in MHz
404 if ($null -eq $cpuDetails.MaxClockSpeed -or $cpuDetails.MaxClockSpeed -le $MinClockSpeedMHz) {
405 UpdateReturnCode -ReturnCode 1;
406 $processorCheckFailed = $true
407 Print-CheckResult $PROCESSOR_STRING $FAIL_STRING "MaxClockSpeed=$($cpuDetails.MaxClockSpeed)MHz, Minimum Required=$MinClockSpeedMHz MHz"
408 $exitCode = 1
409 }
410
411 # Number of Logical Cores
412 if ($null -eq $cpuDetails.NumberOfLogicalProcessors -or $cpuDetails.NumberOfLogicalProcessors -lt $MinLogicalCores) {
413 UpdateReturnCode -ReturnCode 1
414 $processorCheckFailed = $true
415 Print-CheckResult $PROCESSOR_STRING $FAIL_STRING "NumberOfLogicalCores=$($cpuDetails.NumberOfLogicalProcessors), Minimum Required=$MinLogicalCores"
416 $exitCode = 1
417 }
418
419 # CPU Family
420 Add-Type -TypeDefinition $Source
421 $cpuFamilyResult = [CpuFamily]::Validate([String]$cpuDetails.Manufacturer, [uint16]$cpuDetails.Architecture)
422
423 $cpuDetailsLog = "{AddressWidth=$($cpuDetails.AddressWidth); MaxClockSpeed=$($cpuDetails.MaxClockSpeed); NumberOfLogicalCores=$($cpuDetails.NumberOfLogicalProcessors); Manufacturer=$($cpuDetails.Manufacturer); Caption=$($cpuDetails.Caption); $($cpuFamilyResult.Message)}"
424
425 if (!$cpuFamilyResult.IsValid) {
426 UpdateReturnCode -ReturnCode 1
427 $processorCheckFailed = $true
428 Print-CheckResult $PROCESSOR_STRING $FAIL_STRING "$($cpuFamilyResult.Message)"
429 $exitCode = 1
430 }
431
432 if ($processorCheckFailed) {
433 $outObject.returnReason += $logFormatReturnReason -f $PROCESSOR_STRING
434 $outObject.logging += $logFormatWithBlob -f $PROCESSOR_STRING, ($cpuDetailsLog), $FAIL_STRING
435 }
436 else {
437 $outObject.logging += $logFormatWithBlob -f $PROCESSOR_STRING, ($cpuDetailsLog), $PASS_STRING
438 Print-CheckResult $PROCESSOR_STRING $PASS_STRING "$cpuDetailsLog"
439 UpdateReturnCode -ReturnCode 0
440 }
441 }
442}
443catch {
444 UpdateReturnCode -ReturnCode -1
445 $outObject.logging += $logFormat -f $PROCESSOR_STRING, $PROCESSOR_STRING, $UNDETERMINED_STRING, $UNDETERMINED_CAPS_STRING
446 $outObject.logging += $logFormatException -f "$($_.Exception.GetType().Name) $($_.Exception.Message)"
447 Print-CheckResult $PROCESSOR_STRING $UNDETERMINED_CAPS_STRING "Exception: $($_.Exception.Message)"
448 $exitCode = 1
449}
450
451# SecureBooot
452try {
453 $isSecureBootEnabled = Confirm-SecureBootUEFI
454 $outObject.logging += $logFormatWithBlob -f $SECUREBOOT_STRING, $CAPABLE_STRING, $PASS_STRING
455 Print-CheckResult $SECUREBOOT_STRING $PASS_STRING "Secure Boot is enabled"
456 UpdateReturnCode -ReturnCode 0
457}
458catch [System.PlatformNotSupportedException] {
459 # PlatformNotSupportedException "Cmdlet not supported on this platform." - SecureBoot is not supported or is non-UEFI computer.
460 UpdateReturnCode -ReturnCode 1
461 $outObject.returnReason += $logFormatReturnReason -f $SECUREBOOT_STRING
462 $outObject.logging += $logFormatWithBlob -f $SECUREBOOT_STRING, $NOT_CAPABLE_STRING, $FAIL_STRING
463 Print-CheckResult $SECUREBOOT_STRING $FAIL_STRING "SecureBoot is not supported or is non-UEFI computer"
464 $exitCode = 1
465}
466catch [System.UnauthorizedAccessException] {
467 UpdateReturnCode -ReturnCode -1
468 $outObject.logging += $logFormatWithBlob -f $SECUREBOOT_STRING, $UNDETERMINED_STRING, $UNDETERMINED_CAPS_STRING
469 $outObject.logging += $logFormatException -f "$($_.Exception.GetType().Name) $($_.Exception.Message)"
470 Print-CheckResult $SECUREBOOT_STRING $UNDETERMINED_CAPS_STRING "Exception: UnauthorizedAccessException"
471 $exitCode = 1
472}
473catch {
474 UpdateReturnCode -ReturnCode -1
475 $outObject.logging += $logFormatWithBlob -f $SECUREBOOT_STRING, $UNDETERMINED_STRING, $UNDETERMINED_CAPS_STRING
476 $outObject.logging += $logFormatException -f "$($_.Exception.GetType().Name) $($_.Exception.Message)"
477 Print-CheckResult $SECUREBOOT_STRING $UNDETERMINED_CAPS_STRING "Exception: $($_.Exception.Message)"
478 $exitCode = 1
479}
480
481# i7-7820hq CPU
482try {
483 $supportedDevices = @('surface studio 2', 'precision 5520')
484 $systemInfo = @(Get-WmiObject -Class Win32_ComputerSystem)[0]
485
486 if ($null -ne $cpuDetails) {
487 if ($cpuDetails.Name -match 'i7-7820hq cpu @ 2.90ghz'){
488 $modelOrSKUCheckLog = $systemInfo.Model.Trim()
489 if ($supportedDevices -contains $modelOrSKUCheckLog){
490 $outObject.logging += $logFormatWithBlob -f $I7_7820HQ_CPU_STRING, $modelOrSKUCheckLog, $PASS_STRING
491 Print-CheckResult $I7_7820HQ_CPU_STRING $PASS_STRING "Device Model: $modelOrSKUCheckLog"
492 $outObject.returnCode = 0
493 $exitCode = 0
494 }
495 }
496 }
497}
498catch {
499 if ($outObject.returnCode -ne 0){
500 UpdateReturnCode -ReturnCode -1
501 $outObject.logging += $logFormatWithBlob -f $I7_7820HQ_CPU_STRING, $UNDETERMINED_STRING, $UNDETERMINED_CAPS_STRING
502 $outObject.logging += $logFormatException -f "$($_.Exception.GetType().Name) $($_.Exception.Message)"
503 Print-CheckResult $I7_7820HQ_CPU_STRING $UNDETERMINED_CAPS_STRING "Exception: $($_.Exception.Message)"
504 $exitCode = 1
505 }
506}
507
508# Final Result
509Switch ($outObject.returnCode) {
510 0 {
511 $outObject.returnResult = $CAPABLE_CAPS_STRING
512 Write-Color "All checks passed. Device is eligible for Windows 11." "Green"
513 }
514 1 {
515 $outObject.returnResult = $NOT_CAPABLE_CAPS_STRING
516 Write-Color "One or more checks failed. Device is not eligible for Windows 11." "Red"
517 }
518 -1 {
519 $outObject.returnResult = $UNDETERMINED_CAPS_STRING
520 Write-Color "Some checks could not be determined." "Yellow"
521 }
522 -2 {
523 $outObject.returnResult = $FAILED_TO_RUN_STRING
524 Write-Color "The script failed to run." "Red"
525 }
526}
527
528#$outObject | ConvertTo-Json -Compress
529
530# Exit with appropriate code
531if ($exitCode -eq 1) {
532 exit 1
533} else {
534 exit 0
535}
Windows 11 Upgrade - Hardware Check
This PowerShell script evaluates a system's compatibility with Windows 11 by checking hardware and firmware requirements such as disk size, memory, TPM version, processor architecture, secure boot status, and specific CPU models. It provides a detailed pass/fail report for each check and outputs whether the device is capable, not capable, or undetermined for running Windows 11.
PowerShell
300
Local system
Explore more automations, scripts, and policies to further enhance your IT operations.