#Requires -Version 5.1 <# ==================================================================== COREWAY // Windows 11 Readiness Check Uso: irm https://get.coreway.it | iex Autore: Coreway (Andrea Scuttari) - https://coreway.it ==================================================================== #> # --- Durata target della scansione (minuti) ----------------------- $SCAN_MINUTES = 7.5 # <-- unica manopola: alza/abbassa per far durare di più/meno # --- Setup console ------------------------------------------------- $ErrorActionPreference = 'SilentlyContinue' try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch {} try { $Host.UI.RawUI.WindowTitle = 'Coreway // Win11 Readiness Check' } catch {} # Abilita sequenze ANSI su Windows PowerShell 5.1 (VT processing) if ($PSVersionTable.PSVersion.Major -lt 6) { try { Add-Type -Namespace CW -Name Vt -MemberDefinition @' [System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError=true)] public static extern System.IntPtr GetStdHandle(int nStdHandle); [System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError=true)] public static extern bool GetConsoleMode(System.IntPtr h, out uint m); [System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError=true)] public static extern bool SetConsoleMode(System.IntPtr h, uint m); '@ $h = [CW.Vt]::GetStdHandle(-11); $m = 0 [void][CW.Vt]::GetConsoleMode($h, [ref]$m) [void][CW.Vt]::SetConsoleMode($h, $m -bor 0x0004) } catch {} } # --- Palette ANSI -------------------------------------------------- $e = [char]27 $RST = "$e[0m" $B = "$e[1m" $DIM = "$e[2m" $C = @{ cyan = "$e[38;5;44m" blue = "$e[38;5;39m" green = "$e[38;5;46m" red = "$e[38;5;196m" yel = "$e[38;5;220m" gray = "$e[38;5;245m" white = "$e[38;5;231m" mag = "$e[38;5;171m" } function Show($t){ [Console]::Out.Write($t) } function Line($t){ [Console]::Out.WriteLine($t) } # --- Banner -------------------------------------------------------- function Show-Banner { Clear-Host $logo = @( " ██████╗ ██████╗ ██████╗ ███████╗██╗ ██╗ █████╗ ██╗ ██╗", " ██╔════╝██╔═══██╗██╔══██╗██╔════╝██║ ██║██╔══██╗╚██╗ ██╔╝", " ██║ ██║ ██║██████╔╝█████╗ ██║ █╗ ██║███████║ ╚████╔╝ ", " ██║ ██║ ██║██╔══██╗██╔══╝ ██║███╗██║██╔══██║ ╚██╔╝ ", " ╚██████╗╚██████╔╝██║ ██║███████╗╚███╔███╔╝██║ ██║ ██║ ", " ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝ " ) Line "" foreach ($l in $logo) { Line "$B$($C.cyan)$l$RST" } Line "$($C.gray) Windows 11 Readiness Check $($C.white)v1.1$($C.gray) · get.coreway.it$RST" Line "" Line "$($C.gray) ────────────────────────────────────────────────────────────$RST" Line "" } # --- Loop di inizializzazione (puntini) --------------------------- function Show-Boot { $steps = 'Avvio motore di analisi','Caricamento moduli WMI/CIM','Handshake con get.coreway.it' foreach ($s in $steps) { Show " $($C.gray)$s$RST" foreach ($d in 1..3) { Show "$($C.cyan).$RST"; Start-Sleep -Milliseconds 180 } Show " $($C.green)ok$RST`n" } Line "" } # --- Spinner mentre gira un check pesante (con tempo minimo) ------ function Invoke-Step { param([string]$Label, [scriptblock]$Action, [int]$MinMs = 1200) $frames = '⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏' $sw = [System.Diagnostics.Stopwatch]::StartNew() $job = Start-Job -ScriptBlock $Action $i = 0 while ($job.State -eq 'Running' -or $sw.ElapsedMilliseconds -lt $MinMs) { $f = $frames[$i % $frames.Count] Show "`r $($C.cyan)$f$RST $($C.gray)$Label...$RST " Start-Sleep -Milliseconds 90 $i++ } $res = Receive-Job $job; Remove-Job $job Show "`r$(' ' * 72)`r" return $res } # --- Riga di scansione a tempo: barra + contatore che scorrono ---- # La barra arriva al 100% esattamente dopo $Seconds secondi (cronometro reale). function Invoke-Scan { param([string]$Label, [string]$Detail = 'ok', [int]$Total = 0, [double]$Seconds = 20) $frames = '⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏' $col = 30 $dots = '.' * ([math]::Max(2, $col - $Label.Length)) $barW = 16 $sw = [System.Diagnostics.Stopwatch]::StartNew() $targetMs = [double]$Seconds * 1000 $i = 0; $p = 0 while ($sw.ElapsedMilliseconds -lt $targetMs) { $frac = $sw.ElapsedMilliseconds / $targetMs # progresso monotono con micro-jitter, tetto 99% fino alla fine $p = [math]::Min(99, [math]::Max($p, [int]($frac * 100) + (Get-Random -Minimum -1 -Maximum 2))) $fill = [math]::Round($barW * $p / 100) $bar = "$($C.cyan)$('█' * $fill)$DIM$('░' * ($barW - $fill))$RST" $f = $frames[$i % $frames.Count]; $i++ $cnt = if ($Total -gt 0) { "$($C.gray)[$('{0,5}' -f [int]($Total * $p / 100)) / $Total ]$RST" } else { '' } Show "`r $($C.cyan)$f$RST $($C.white)$Label$RST$($C.gray)$dots$RST $($C.gray)▕$bar$($C.gray)▏$RST $($C.yel)$('{0,3}' -f $p)%$RST $cnt " Start-Sleep -Milliseconds (Get-Random -Minimum 110 -Maximum 190) } $cntDone = if ($Total -gt 0) { "$($C.gray)[$('{0,5}' -f $Total) / $Total ]$RST" } else { '' } Show "`r $($C.green)✔$RST $($C.white)$Label$RST$($C.gray)$dots$RST $($C.gray)▕$($C.green)$('█' * $barW)$($C.gray)▏$RST $($C.green)done$RST $cntDone $($C.gray)$Detail$RST$(' ' * 6)`n" } # --- Riga risultato requisito ------------------------------------- function Write-Result { param([string]$Name, [bool]$Ok, [string]$Detail, [bool]$Warn = $false) $pad = $Name.PadRight(24) if ($Warn) { $icon = "$($C.yel)▲$RST"; $col = $C.yel } elseif ($Ok) { $icon = "$($C.green)✔$RST"; $col = $C.green } else { $icon = "$($C.red)✘$RST"; $col = $C.red } Line " $icon $($C.white)$pad$RST $col$Detail$RST" } # ================================================================== # MAIN # ================================================================== Show-Banner Show-Boot # --- Info macchina ------------------------------------------------- $os = Get-CimInstance Win32_OperatingSystem $cs = Get-CimInstance Win32_ComputerSystem $cpu = Get-CimInstance Win32_Processor | Select-Object -First 1 $bios = Get-CimInstance Win32_BIOS $ramGB = [math]::Round($cs.TotalPhysicalMemory / 1GB, 1) $sysDrv = ($env:SystemDrive) $disk = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='$sysDrv'" $diskGB = [math]::Round($disk.Size / 1GB, 0) $freeGB = [math]::Round($disk.FreeSpace / 1GB, 0) $isWin11 = [int]($os.BuildNumber) -ge 22000 Line "$B$($C.blue) SISTEMA$RST" Line " $($C.gray)Host $RST $($C.white)$($env:COMPUTERNAME)$RST $($C.gray)· $($cs.Manufacturer) $($cs.Model)$RST" Line " $($C.gray)OS $RST $($C.white)$($os.Caption) $($C.gray)build $($os.BuildNumber)$RST" Line " $($C.gray)CPU $RST $($C.white)$($cpu.Name.Trim())$RST" Line " $($C.gray)RAM $RST $($C.white)$ramGB GB$RST $($C.gray)Disco $sysDrv $freeGB/$diskGB GB liberi$RST" Line "" # --- Inventario reale (contatori per la scansione) ---------------- $inv = Invoke-Step "Raccolta inventario di sistema" { [pscustomobject]@{ Proc = @(Get-Process).Count Svc = @(Get-Service).Count Drv = @(Get-CimInstance Win32_SystemDriver -ErrorAction SilentlyContinue).Count Net = @(Get-CimInstance Win32_PnPEntity -Filter "PNPClass='Net'" -ErrorAction SilentlyContinue).Count Vol = @(Get-CimInstance Win32_LogicalDisk -ErrorAction SilentlyContinue).Count Mem = @(Get-CimInstance Win32_PhysicalMemory -ErrorAction SilentlyContinue).Count Hotfix = @(Get-CimInstance Win32_QuickFixEngineering -ErrorAction SilentlyContinue).Count Pnp = @(Get-CimInstance Win32_PnPEntity -ErrorAction SilentlyContinue).Count } } 4000 if (-not $inv) { $inv = [pscustomobject]@{ Proc=0;Svc=0;Drv=0;Net=0;Vol=0;Mem=0;Hotfix=0;Pnp=0 } } $cores = $cpu.NumberOfCores $threads = $cpu.NumberOfLogicalProcessors $ghz = [math]::Round($cpu.MaxClockSpeed / 1000, 1) # --- SCANSIONE SISTEMA (loop animati, durata ~ $SCAN_MINUTES) ----- # Ogni voce ha un peso W: il tempo totale viene ripartito sui pesi. $scanItems = @( @{ L='Processore'; D="$cores core / $threads thread @ $ghz GHz"; T=0; W=5 }, @{ L='Memoria RAM'; D="$ramGB GB su $($inv.Mem) modulo/i"; T=$inv.Mem; W=5 }, @{ L='Volumi di archiviazione'; D="$diskGB GB · $freeGB GB liberi"; T=$inv.Vol; W=6 }, @{ L='Periferiche PnP'; D="hardware enumerato"; T=$inv.Pnp; W=10 }, @{ L='Driver di sistema'; D="firmati e coerenti"; T=$inv.Drv; W=11 }, @{ L='Servizi di Windows'; D="stato verificato"; T=$inv.Svc; W=9 }, @{ L='Processi in esecuzione'; D="nessuna anomalia"; T=$inv.Proc; W=7 }, @{ L='Adattatori di rete'; D="connettivita ok"; T=$inv.Net; W=6 }, @{ L='Firmware / UEFI'; D="modalita rilevata"; T=0; W=5 }, @{ L='Modulo TPM'; D="chip di sicurezza interrogato"; T=0; W=6 }, @{ L='Criteri Secure Boot'; D="policy di avvio"; T=0; W=5 }, @{ L='Registro di sistema'; D="integro"; T=0; W=10 }, @{ L='Integrita file di sistema';D="nessun errore rilevato"; T=0; W=11 }, @{ L='Aggiornamenti installati'; D="cronologia patch"; T=$inv.Hotfix; W=9 } ) $wSum = ($scanItems | Measure-Object -Property W -Sum).Sum $budget = [double]$SCAN_MINUTES * 60 Line "$B$($C.blue) SCANSIONE SISTEMA$RST" foreach ($it in $scanItems) { $sec = [math]::Max(6, [math]::Round($budget * $it.W / $wSum, 1)) Invoke-Scan $it.L $it.D $it.T $sec } Line "" # ================================================================== # REQUISITI WINDOWS 11 (check autorevoli) # ================================================================== Line "$B$($C.blue) REQUISITI WINDOWS 11$RST" $pass = 0; $total = 0 # 1) TPM 2.0 $total++ $tpm = Invoke-Step "Verifica TPM" { Get-CimInstance -Namespace 'Root\CIMV2\Security\MicrosoftTpm' -ClassName Win32_Tpm } $tpmOk = $false; $tpmDet = "Non rilevato" if ($tpm) { $ver = ($tpm.SpecVersion -split ',')[0].Trim() $tpmOk = ($tpm.IsEnabled_InitialValue -and [double]$ver -ge 2.0) $tpmDet = if ($tpmOk) { "Presente e attivo (spec $ver)" } else { "Presente ma spec $ver / disabilitato" } } if ($tpmOk) { $pass++ } Write-Result "TPM 2.0" $tpmOk $tpmDet # 2) Secure Boot $total++ $sb = Invoke-Step "Verifica Secure Boot" { try { Confirm-SecureBootUEFI } catch { 'ND' } } $sbOk = ($sb -eq $true) $sbDet = if ($sb -eq $true) { "Abilitato" } elseif ($sb -eq $false) { "Disabilitato (attivabile da UEFI)" } else { "Non disponibile (BIOS Legacy)" } if ($sbOk) { $pass++ } Write-Result "Secure Boot" $sbOk $sbDet -Warn:($sb -eq $false) # 3) Firmware UEFI $total++ $uefi = $env:firmware_type if (-not $uefi) { $uefi = if (Test-Path 'HKLM:\System\CurrentControlSet\Control\SecureBoot\State') { 'UEFI' } else { 'Legacy' } } $uefiOk = ($uefi -match 'UEFI') if ($uefiOk) { $pass++ } Write-Result "Firmware UEFI" $uefiOk $(if ($uefiOk){"UEFI"}else{"Legacy BIOS (non supportato)"}) # 4) CPU: 64-bit, >=2 core, >=1 GHz $total++ $arch = $cpu.AddressWidth $cpuOk = ($arch -eq 64 -and $cores -ge 2 -and $cpu.MaxClockSpeed -ge 1000) if ($cpuOk) { $pass++ } Write-Result "CPU" $cpuOk "$cores core · $ghz GHz · ${arch}-bit" # 5) RAM >= 4 GB $total++ $ramOk = ($ramGB -ge 4) if ($ramOk) { $pass++ } Write-Result "RAM (>= 4 GB)" $ramOk "$ramGB GB installati" # 6) Disco sistema >= 64 GB $total++ $diskOk = ($diskGB -ge 64) if ($diskOk) { $pass++ } Write-Result "Storage (>= 64 GB)" $diskOk "$diskGB GB totali su $sysDrv" # 7) DirectX 12 / WDDM 2.0 $total++ $dxOk = $isWin11 -or ([int]$os.BuildNumber -ge 15063) # euristica: Win10 1703+ ha DX12/WDDM2 if ($dxOk) { $pass++ } Write-Result "DirectX 12 / WDDM 2.0" $dxOk $(if ($dxOk){"Supportato"}else{"Da verificare (dxdiag)"}) -Warn:(-not $isWin11) # --- Barra di avanzamento riepilogo ------------------------------- Line "" $pct = [math]::Round(($pass / $total) * 100) $barW = 40 $fill = [math]::Round($barW * $pass / $total) $barCol = if ($pct -eq 100) { $C.green } elseif ($pct -ge 70) { $C.yel } else { $C.red } $bar = ('█' * $fill) + ($DIM + '░' * ($barW - $fill) + $RST) Line " $barCol$bar$RST $B$barCol$pct%$RST $($C.gray)($pass/$total)$RST" Line "" Line "$($C.gray) ────────────────────────────────────────────────────────────$RST" # --- Verdetto ------------------------------------------------------ Line "" if ($isWin11) { Line " $B$($C.green)● Questo PC ha già Windows 11 installato.$RST" } elseif ($pass -eq $total) { Line " $B$($C.green)● COMPATIBILE — questo PC può eseguire l'upgrade a Windows 11.$RST" } elseif ($pass -ge ($total - 1)) { Line " $B$($C.yel)▲ QUASI PRONTO — sistema aggiustabile da UEFI/BIOS.$RST" Line " $($C.gray) Abilita TPM e Secure Boot nel firmware e ripeti il check.$RST" } else { Line " $B$($C.red)● NON COMPATIBILE — mancano requisiti hardware per Windows 11.$RST" } Line "" Line "$($C.gray) Serve una mano con l'upgrade o la configurazione UEFI?$RST" Line "$($C.cyan) ➜ Coreway · https://coreway.it · Padova$RST" Line "" # --- Pausa solo se sessione interattiva --------------------------- if ($Host.Name -eq 'ConsoleHost' -and -not $env:CI) { Show "$($C.gray) Premi un tasto per chiudere...$RST" try { [void]$Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') } catch { Start-Sleep 2 } Line "" }