diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 8aaa3b51..53b3922c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -65,6 +65,7 @@ body: label: Windows OS Version description: Which Windows version? options: + - Windows 11 26H2 - Windows 11 25H2 - Windows 11 24H2 - Windows 11 23H2 diff --git a/WinToolkit.ps1 b/WinToolkit.ps1 index 136f1c95..1626b544 100644 --- a/WinToolkit.ps1 +++ b/WinToolkit.ps1 @@ -576,9 +576,7 @@ function Start-ToolkitLog { $remoteVer = if ($PSVersionTable.PSRemotingProtocolVersion) { $PSVersionTable.PSRemotingProtocolVersion.ToString() } else { 'N/A' } $serVer = if ($PSVersionTable.SerializationVersion) { $PSVersionTable.SerializationVersion.ToString() } else { 'N/A' } $build = [int]$os.BuildNumber - $verMap = @{26100 = '24H2'; 22631 = '23H2'; 22621 = '22H2'; 22000 = '21H2'; 19045 = '22H2'; 19044 = '21H2' } - $dispVer = 'N/A' - foreach ($k in ($verMap.Keys | Sort-Object -Descending)) { if ($build -ge $k) { $dispVer = $verMap[$k]; break } } + $dispVer = Get-WindowsDisplayVersion -Build $build $header = @" [START LOG HEADER] Start time : $dateTime @@ -649,25 +647,56 @@ function Write-ToolkitError { Stack = $Record.ScriptStackTrace } } +function Get-WindowsDisplayVersion { + param([int]$Build = 0) + if ($Build -le 0) { + try { $Build = [int](Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue).BuildNumber } catch { $Build = 0 } + } + $ntKey = $null + try { $ntKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -ErrorAction SilentlyContinue } catch { $ntKey = $null } + if ($ntKey) { + if ($ntKey.DisplayVersion) { + $displayVersion = ([string]$ntKey.DisplayVersion).Trim() + if ($displayVersion) { return $displayVersion } + } + if ($ntKey.ReleaseId -and $Build -lt 22000) { + $releaseId = ([string]$ntKey.ReleaseId).Trim() + if ($releaseId) { return $releaseId } + } + } + $versionMap = @{ + 28000 = "26H1"; 26300 = "26H2"; 26200 = "25H2"; 26100 = "24H2" + 22631 = "23H2"; 22621 = "22H2"; 22000 = "21H2" + 19045 = "22H2"; 19044 = "21H2"; 19043 = "21H1"; 19042 = "20H2" + 19041 = "2004"; 18363 = "1909"; 18362 = "1903"; 17763 = "1809" + 17134 = "1803"; 16299 = "1709"; 15063 = "1703"; 14393 = "1607" + 10586 = "1511"; 10240 = "1507" + } + foreach ($key in ($versionMap.Keys | Sort-Object -Descending)) { + if ($Build -ge $key) { return $versionMap[$key] } + } + return "N/A" +} +function Get-WindowsCompatibility { + param([int]$Build) + if ($Build -ge 22000) { return 'Windows11' } + if ($Build -ge 17763) { return 'Windows10' } + if ($Build -eq 9600) { return 'Windows81' } + return 'Unsupported' +} function Get-SystemInfo { if ($Global:SystemInfoCache) { return $Global:SystemInfoCache } try { $osInfo = Get-CimInstance Win32_OperatingSystem $computerInfo = Get-CimInstance Win32_ComputerSystem $diskInfo = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='C:'" - $versionMap = @{ - 28000 = "26H1"; 26200 = "25H2"; 26100 = "24H2"; 22631 = "23H2"; 22621 = "22H2"; 22000 = "21H2" - 19045 = "22H2"; 19044 = "21H2"; 19043 = "21H1"; 19042 = "20H2"; 19041 = "2004"; 18363 = "1909" - 18362 = "1903"; 17763 = "1809"; 17134 = "1803"; 16299 = "1709"; 15063 = "1703"; 14393 = "1607" - 10586 = "1511"; 10240 = "1507" - } $build = [int]$osInfo.BuildNumber - $ver = "N/A" - foreach ($k in ($versionMap.Keys | Sort-Object -Descending)) { if ($build -ge $k) { $ver = $versionMap[$k]; break } } + $ver = Get-WindowsDisplayVersion -Build $build $Global:SystemInfoCache = @{ ProductName = $osInfo.Caption -replace 'Microsoft ', '' BuildNumber = $build DisplayVersion = $ver + Compatibility = Get-WindowsCompatibility -Build $build Architecture = $osInfo.OSArchitecture ComputerName = $computerInfo.Name TotalRAM = [Math]::Round($computerInfo.TotalPhysicalMemory / 1GB, 2) @@ -1669,14 +1698,16 @@ function WinOSCheck { $si = Get-SystemInfo if (-not $si) { Write-StyledMessage -Type 'Warning' -Text (Get-SourceTextLoc 'uiText.systemInfoNotAvailable'); return } Write-StyledMessage -Type 'Info' -Text (Get-SourceTextLoc 'uiText.system01' -Args @($($si.ProductName), $($si.DisplayVersion))) - if ($si.BuildNumber -ge 22000) { Write-StyledMessage -Type 'Success' -Text (Get-SourceTextLoc 'uiText.compatibleSystemRecentWin1110') } - elseif ($si.BuildNumber -ge 17763) { Write-StyledMessage -Type 'Success' -Text (Get-SourceTextLoc 'uiText.compatibleSystemWin10') } - elseif ($si.BuildNumber -eq 9600) { Write-StyledMessage -Type 'Warning' -Text (Get-SourceTextLoc 'uiText.windows81PartialCompatibility') } - else { - Write-StyledMessage -Type 'Error' -Text "$(Get-CenteredText ('🤣 ' + (Get-SourceTextLoc 'sourceText.criticalError').ToUpperInvariant() + ' 🤣') 65)" - Write-StyledMessage -Type 'Error' -Text (Get-SourceTextLoc 'uiText.doYouReallyThinkThisScriptCanDoAnythingForThisVersion') - Write-Host (" " + (Get-SourceTextLoc 'uiText.doYouWantToTakeARiskYN')) -ForegroundColor Yellow - if ((Read-Host) -notmatch '^[Yy]$') { exit } + switch ($si.Compatibility) { + 'Windows11' { Write-StyledMessage -Type 'Success' -Text (Get-SourceTextLoc 'uiText.compatibleSystemRecentWin1110') } + 'Windows10' { Write-StyledMessage -Type 'Success' -Text (Get-SourceTextLoc 'uiText.compatibleSystemWin10') } + 'Windows81' { Write-StyledMessage -Type 'Warning' -Text (Get-SourceTextLoc 'uiText.windows81PartialCompatibility') } + default { + Write-StyledMessage -Type 'Error' -Text "$(Get-CenteredText ('🤣 ' + (Get-SourceTextLoc 'sourceText.criticalError').ToUpperInvariant() + ' 🤣') 65)" + Write-StyledMessage -Type 'Error' -Text (Get-SourceTextLoc 'uiText.doYouReallyThinkThisScriptCanDoAnythingForThisVersion') + Write-Host (" " + (Get-SourceTextLoc 'uiText.doYouWantToTakeARiskYN')) -ForegroundColor Yellow + if ((Read-Host) -notmatch '^[Yy]$') { exit } + } } Start-Sleep -Seconds 2 } diff --git a/WinToolkit_GUI.ps1 b/WinToolkit_GUI.ps1 index e823102e..34d6eb46 100644 --- a/WinToolkit_GUI.ps1 +++ b/WinToolkit_GUI.ps1 @@ -18,7 +18,7 @@ $Global:GuiSessionActive = $true # ============================================================================= # GUI VERSION CONFIGURATION (Separate from Core Version) # ============================================================================= -$Global:GuiVersion = "3.1.0 (Build 12)" # Format: CoreVersion.GuiBuildNumber +$Global:GuiVersion = "3.1.0 (Build 13)" # Format: CoreVersion.GuiBuildNumber # ============================================================================= # CONFIGURATION AND CONSTANTS @@ -1884,29 +1884,28 @@ function Update-SystemInformationPanel { Write-UnifiedLog -Type 'Warning' -Message (Get-SourceTextLoc 'uiText.couldNotLoadSomeIcons0' -Args @($($_.Exception.Message))) -GuiColor "#FFA500" } - # Task 2: Compatibility indicator with colored status text + # Task 2: Compatibility indicator with colored status text. + # Compatibility is computed by the core (Get-SystemInfo) so the GUI only + # renders the already-classified tier and stays version-logic free. $statusText = "" $statusIconKey = "LEDStatusRed" - if ($sysInfo.BuildNumber -ge 22000) { - $statusText = Get-SourceTextLoc 'gui.complete' - $statusIconKey = "LEDStatusGreen" - $SysInfoScriptCompatibility.Foreground = New-Object System.Windows.Media.SolidColorBrush([System.Windows.Media.Colors]::LimeGreen) - } - elseif ($sysInfo.BuildNumber -ge 17763) { - $statusText = Get-SourceTextLoc 'gui.complete' - $statusIconKey = "LEDStatusGreen" - $SysInfoScriptCompatibility.Foreground = New-Object System.Windows.Media.SolidColorBrush([System.Windows.Media.Colors]::LimeGreen) - } - elseif ($sysInfo.BuildNumber -ge 10240) { - $statusText = Get-SourceTextLoc 'gui.limited' - $statusIconKey = "LEDStatusYellow" - $SysInfoScriptCompatibility.Foreground = New-Object System.Windows.Media.SolidColorBrush([System.Windows.Media.Colors]::Orange) - } - else { - $statusText = Get-SourceTextLoc 'gui.unsupported' - $statusIconKey = "LEDStatusRed" - $SysInfoScriptCompatibility.Foreground = New-Object System.Windows.Media.SolidColorBrush([System.Windows.Media.Colors]::Red) + switch ($sysInfo.Compatibility) { + { $_ -in 'Windows11', 'Windows10' } { + $statusText = Get-SourceTextLoc 'gui.complete' + $statusIconKey = "LEDStatusGreen" + $SysInfoScriptCompatibility.Foreground = New-Object System.Windows.Media.SolidColorBrush([System.Windows.Media.Colors]::LimeGreen) + } + 'Windows81' { + $statusText = Get-SourceTextLoc 'gui.limited' + $statusIconKey = "LEDStatusYellow" + $SysInfoScriptCompatibility.Foreground = New-Object System.Windows.Media.SolidColorBrush([System.Windows.Media.Colors]::Orange) + } + default { + $statusText = Get-SourceTextLoc 'gui.unsupported' + $statusIconKey = "LEDStatusRed" + $SysInfoScriptCompatibility.Foreground = New-Object System.Windows.Media.SolidColorBrush([System.Windows.Media.Colors]::Red) + } } $SysInfoScriptCompatibility.Text = $statusText diff --git a/wintoolkit-modules/30-Module.Logging.ps1 b/wintoolkit-modules/30-Module.Logging.ps1 index 7efab857..bd02d891 100644 --- a/wintoolkit-modules/30-Module.Logging.ps1 +++ b/wintoolkit-modules/30-Module.Logging.ps1 @@ -34,9 +34,7 @@ function Start-ToolkitLog { $serVer = if ($PSVersionTable.SerializationVersion) { $PSVersionTable.SerializationVersion.ToString() } else { 'N/A' } $build = [int]$os.BuildNumber - $verMap = @{26100 = '24H2'; 22631 = '23H2'; 22621 = '22H2'; 22000 = '21H2'; 19045 = '22H2'; 19044 = '21H2' } - $dispVer = 'N/A' - foreach ($k in ($verMap.Keys | Sort-Object -Descending)) { if ($build -ge $k) { $dispVer = $verMap[$k]; break } } + $dispVer = Get-WindowsDisplayVersion -Build $build $header = @" [START LOG HEADER] diff --git a/wintoolkit-modules/40-Module.System.ps1 b/wintoolkit-modules/40-Module.System.ps1 index 83f718c5..8681f8e0 100644 --- a/wintoolkit-modules/40-Module.System.ps1 +++ b/wintoolkit-modules/40-Module.System.ps1 @@ -4,26 +4,85 @@ # Data collection on the operating system, hardware and security services. # ============================================================================== +function Get-WindowsDisplayVersion { + <# + .SYNOPSIS + Restituisce l'etichetta della release di Windows (es. 24H2, 25H2, 26H1, 26H2). + .DESCRIPTION + Il valore DisplayVersion del registro è la fonte autorevole e resta corretto + anche quando una release non segue l'ordine del build number: 26H1 gira su + build 28000 mentre 26H2 gira su build 26300. Senza DisplayVersion + (Windows 10) si usa ReleaseId, quindi una mappa build-to-version come ultimo + fallback, in modo che le versioni future siano riconosciute senza patch. + #> + param([int]$Build = 0) + + if ($Build -le 0) { + try { $Build = [int](Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue).BuildNumber } catch { $Build = 0 } + } + + $ntKey = $null + try { $ntKey = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -ErrorAction SilentlyContinue } catch { $ntKey = $null } + + if ($ntKey) { + if ($ntKey.DisplayVersion) { + $displayVersion = ([string]$ntKey.DisplayVersion).Trim() + if ($displayVersion) { return $displayVersion } + } + if ($ntKey.ReleaseId -and $Build -lt 22000) { + $releaseId = ([string]$ntKey.ReleaseId).Trim() + if ($releaseId) { return $releaseId } + } + } + + $versionMap = @{ + 28000 = "26H1"; 26300 = "26H2"; 26200 = "25H2"; 26100 = "24H2" + 22631 = "23H2"; 22621 = "22H2"; 22000 = "21H2" + 19045 = "22H2"; 19044 = "21H2"; 19043 = "21H1"; 19042 = "20H2" + 19041 = "2004"; 18363 = "1909"; 18362 = "1903"; 17763 = "1809" + 17134 = "1803"; 16299 = "1709"; 15063 = "1703"; 14393 = "1607" + 10586 = "1511"; 10240 = "1507" + } + foreach ($key in ($versionMap.Keys | Sort-Object -Descending)) { + if ($Build -ge $key) { return $versionMap[$key] } + } + return "N/A" +} + + +function Get-WindowsCompatibility { + <# + .SYNOPSIS + Classifica la compatibilità del sistema operativo a partire dal build number. + .DESCRIPTION + Mappa il build number in una categoria logica usata da GUI, banner e messaggi + di verifica: Windows 11 (build >= 22000), Windows 10 (17763-21999), + Windows 8.1 (9600), altrimenti Unsupported. Centralizzata qui così la GUI non + deve interpretare il build number e basta un punto di update per nuove release. + #> + param([int]$Build) + + if ($Build -ge 22000) { return 'Windows11' } + if ($Build -ge 17763) { return 'Windows10' } + if ($Build -eq 9600) { return 'Windows81' } + return 'Unsupported' +} + + function Get-SystemInfo { if ($Global:SystemInfoCache) { return $Global:SystemInfoCache } try { $osInfo = Get-CimInstance Win32_OperatingSystem $computerInfo = Get-CimInstance Win32_ComputerSystem $diskInfo = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='C:'" - $versionMap = @{ - 28000 = "26H1"; 26200 = "25H2"; 26100 = "24H2"; 22631 = "23H2"; 22621 = "22H2"; 22000 = "21H2" - 19045 = "22H2"; 19044 = "21H2"; 19043 = "21H1"; 19042 = "20H2"; 19041 = "2004"; 18363 = "1909" - 18362 = "1903"; 17763 = "1809"; 17134 = "1803"; 16299 = "1709"; 15063 = "1703"; 14393 = "1607" - 10586 = "1511"; 10240 = "1507" - } $build = [int]$osInfo.BuildNumber - $ver = "N/A" - foreach ($k in ($versionMap.Keys | Sort-Object -Descending)) { if ($build -ge $k) { $ver = $versionMap[$k]; break } } + $ver = Get-WindowsDisplayVersion -Build $build $Global:SystemInfoCache = @{ ProductName = $osInfo.Caption -replace 'Microsoft ', '' BuildNumber = $build DisplayVersion = $ver + Compatibility = Get-WindowsCompatibility -Build $build Architecture = $osInfo.OSArchitecture ComputerName = $computerInfo.Name TotalRAM = [Math]::Round($computerInfo.TotalPhysicalMemory / 1GB, 2) diff --git a/wintoolkit-modules/80-Module.UserInteraction.ps1 b/wintoolkit-modules/80-Module.UserInteraction.ps1 index cab5ee9b..f4de69b1 100644 --- a/wintoolkit-modules/80-Module.UserInteraction.ps1 +++ b/wintoolkit-modules/80-Module.UserInteraction.ps1 @@ -98,14 +98,16 @@ function WinOSCheck { Write-StyledMessage -Type 'Info' -Text (Get-SourceTextLoc 'uiText.system01' -Args @($($si.ProductName), $($si.DisplayVersion))) - if ($si.BuildNumber -ge 22000) { Write-StyledMessage -Type 'Success' -Text (Get-SourceTextLoc 'uiText.compatibleSystemRecentWin1110') } - elseif ($si.BuildNumber -ge 17763) { Write-StyledMessage -Type 'Success' -Text (Get-SourceTextLoc 'uiText.compatibleSystemWin10') } - elseif ($si.BuildNumber -eq 9600) { Write-StyledMessage -Type 'Warning' -Text (Get-SourceTextLoc 'uiText.windows81PartialCompatibility') } - else { - Write-StyledMessage -Type 'Error' -Text "$(Get-CenteredText ('🤣 ' + (Get-SourceTextLoc 'sourceText.criticalError').ToUpperInvariant() + ' 🤣') 65)" - Write-StyledMessage -Type 'Error' -Text (Get-SourceTextLoc 'uiText.doYouReallyThinkThisScriptCanDoAnythingForThisVersion') - Write-Host (" " + (Get-SourceTextLoc 'uiText.doYouWantToTakeARiskYN')) -ForegroundColor Yellow - if ((Read-Host) -notmatch '^[Yy]$') { exit } + switch ($si.Compatibility) { + 'Windows11' { Write-StyledMessage -Type 'Success' -Text (Get-SourceTextLoc 'uiText.compatibleSystemRecentWin1110') } + 'Windows10' { Write-StyledMessage -Type 'Success' -Text (Get-SourceTextLoc 'uiText.compatibleSystemWin10') } + 'Windows81' { Write-StyledMessage -Type 'Warning' -Text (Get-SourceTextLoc 'uiText.windows81PartialCompatibility') } + default { + Write-StyledMessage -Type 'Error' -Text "$(Get-CenteredText ('🤣 ' + (Get-SourceTextLoc 'sourceText.criticalError').ToUpperInvariant() + ' 🤣') 65)" + Write-StyledMessage -Type 'Error' -Text (Get-SourceTextLoc 'uiText.doYouReallyThinkThisScriptCanDoAnythingForThisVersion') + Write-Host (" " + (Get-SourceTextLoc 'uiText.doYouWantToTakeARiskYN')) -ForegroundColor Yellow + if ((Read-Host) -notmatch '^[Yy]$') { exit } + } } Start-Sleep -Seconds 2 }