Created
November 3, 2025 08:11
-
-
Save daemondevin/e6a7199e1c625a52bfbf5b07c73b76de to your computer and use it in GitHub Desktop.
Modern Windows Version Detection Optimized for Windows 10, 11, and current Server versions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ; ModernWinVer.nsh - Modern Windows Version Detection | |
| ; Optimized for Windows 10, 11, and current Server versions | |
| ; Extends and modernizes the standard WinVer.nsh | |
| !ifndef MODERN_WINVER_NSH | |
| !define MODERN_WINVER_NSH | |
| !include LogicLib.nsh | |
| ; Windows Version Constants (Major.Minor.Build) | |
| !define WINVER_10 10.0 ; Windows 10 / Server 2016+ | |
| !define WINVER_11_BUILD 22000 ; Windows 11 minimum build | |
| ; Windows 10/11 Version Numbers (Builds) | |
| !define WIN10_1507 10240 ; Windows 10 RTM (July 2015) | |
| !define WIN10_1511 10586 ; November Update | |
| !define WIN10_1607 14393 ; Anniversary Update / Server 2016 | |
| !define WIN10_1703 15063 ; Creators Update | |
| !define WIN10_1709 16299 ; Fall Creators Update | |
| !define WIN10_1803 17134 ; April 2018 Update | |
| !define WIN10_1809 17763 ; October 2018 Update / Server 2019 | |
| !define WIN10_1903 18362 ; May 2019 Update | |
| !define WIN10_1909 18363 ; November 2019 Update | |
| !define WIN10_2004 19041 ; May 2020 Update | |
| !define WIN10_20H2 19042 ; October 2020 Update | |
| !define WIN10_21H1 19043 ; May 2021 Update | |
| !define WIN10_21H2 19044 ; November 2021 Update | |
| !define WIN10_22H2 19045 ; October 2022 Update (Final) | |
| ; Windows 11 Version Numbers (Builds) | |
| !define WIN11_21H2 22000 ; Windows 11 RTM (October 2021) | |
| !define WIN11_22H2 22621 ; September 2022 Update | |
| !define WIN11_23H2 22631 ; October 2023 Update | |
| !define WIN11_24H2 26100 ; September 2024 Update | |
| ; Windows Server Version Numbers | |
| !define WINSERVER_2016 14393 | |
| !define WINSERVER_2019 17763 | |
| !define WINSERVER_2022 20348 | |
| !define WINSERVER_2025 26100 ; Expected build (may vary) | |
| ; Product Type Constants | |
| !define VER_NT_WORKSTATION 1 | |
| !define VER_NT_DOMAIN_CONTROLLER 2 | |
| !define VER_NT_SERVER 3 | |
| ; Architecture Constants | |
| !define ARCH_X86 "x86" | |
| !define ARCH_X64 "x64" | |
| !define ARCH_ARM64 "ARM64" | |
| ;------------------------------------------------------------ | |
| ; IsWindows11 | |
| ; Returns true if running Windows 11 or later | |
| ;------------------------------------------------------------ | |
| !macro IsWindows11 _RESULT | |
| Push $0 | |
| Push $1 | |
| ; Get build number | |
| ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentBuild" | |
| IntCmp $0 ${WINVER_11_BUILD} 0 not_win11 is_win11 | |
| is_win11: | |
| StrCpy ${_RESULT} 1 | |
| Goto done | |
| not_win11: | |
| StrCpy ${_RESULT} 0 | |
| done: | |
| Pop $1 | |
| Pop $0 | |
| !macroend | |
| !define IsWindows11 "!insertmacro IsWindows11" | |
| ;------------------------------------------------------------ | |
| ; IsWindows10 | |
| ; Returns true if running Windows 10 (not 11) | |
| ;------------------------------------------------------------ | |
| !macro IsWindows10 _RESULT | |
| Push $0 | |
| Push $1 | |
| ; Get version | |
| ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentMajorVersionNumber" | |
| ReadRegStr $1 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentBuild" | |
| ${If} $0 == "10" | |
| IntCmp $1 ${WINVER_11_BUILD} not_win10 not_win10 is_win10 | |
| is_win10: | |
| StrCpy ${_RESULT} 1 | |
| Goto done | |
| ${EndIf} | |
| not_win10: | |
| StrCpy ${_RESULT} 0 | |
| done: | |
| Pop $1 | |
| Pop $0 | |
| !macroend | |
| !define IsWindows10 "!insertmacro IsWindows10" | |
| ;------------------------------------------------------------ | |
| ; IsWindowsServer | |
| ; Returns true if running Windows Server edition | |
| ;------------------------------------------------------------ | |
| !macro IsWindowsServer _RESULT | |
| Push $0 | |
| System::Call 'kernel32::GetVersion()i.r0' | |
| ; Check if it's a server using registry | |
| ReadRegDWORD $0 HKLM "SYSTEM\CurrentControlSet\Control\ProductOptions" "ProductType" | |
| ${If} $0 == ${VER_NT_DOMAIN_CONTROLLER} | |
| ${OrIf} $0 == ${VER_NT_SERVER} | |
| StrCpy ${_RESULT} 1 | |
| ${Else} | |
| StrCpy ${_RESULT} 0 | |
| ${EndIf} | |
| Pop $0 | |
| !macroend | |
| !define IsWindowsServer "!insertmacro IsWindowsServer" | |
| ;------------------------------------------------------------ | |
| ; GetWindowsBuild | |
| ; Returns the Windows build number as a string | |
| ;------------------------------------------------------------ | |
| !macro GetWindowsBuild _RESULT | |
| ReadRegStr ${_RESULT} HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentBuild" | |
| !macroend | |
| !define GetWindowsBuild "!insertmacro GetWindowsBuild" | |
| ;------------------------------------------------------------ | |
| ; GetWindowsVersion | |
| ; Returns a readable Windows version string | |
| ;------------------------------------------------------------ | |
| !macro GetWindowsVersion _RESULT | |
| Push $0 | |
| Push $1 | |
| ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentBuild" | |
| ; Check for Windows 11 | |
| IntCmp $0 ${WIN11_24H2} 0 +3 0 | |
| StrCpy ${_RESULT} "Windows 11 24H2" | |
| Goto done | |
| IntCmp $0 ${WIN11_23H2} 0 +3 0 | |
| StrCpy ${_RESULT} "Windows 11 23H2" | |
| Goto done | |
| IntCmp $0 ${WIN11_22H2} 0 +3 0 | |
| StrCpy ${_RESULT} "Windows 11 22H2" | |
| Goto done | |
| IntCmp $0 ${WIN11_21H2} 0 +3 0 | |
| StrCpy ${_RESULT} "Windows 11 21H2" | |
| Goto done | |
| ; Check if it's Server | |
| ${IsWindowsServer} $1 | |
| ${If} $1 == 1 | |
| IntCmp $0 ${WINSERVER_2025} 0 +3 0 | |
| StrCpy ${_RESULT} "Windows Server 2025" | |
| Goto done | |
| IntCmp $0 ${WINSERVER_2022} 0 +3 0 | |
| StrCpy ${_RESULT} "Windows Server 2022" | |
| Goto done | |
| IntCmp $0 ${WINSERVER_2019} 0 +3 0 | |
| StrCpy ${_RESULT} "Windows Server 2019" | |
| Goto done | |
| IntCmp $0 ${WINSERVER_2016} 0 +3 0 | |
| StrCpy ${_RESULT} "Windows Server 2016" | |
| Goto done | |
| StrCpy ${_RESULT} "Windows Server (Unknown)" | |
| Goto done | |
| ${EndIf} | |
| ; Check for Windows 10 | |
| IntCmp $0 ${WIN10_22H2} 0 +3 0 | |
| StrCpy ${_RESULT} "Windows 10 22H2" | |
| Goto done | |
| IntCmp $0 ${WIN10_21H2} 0 +3 0 | |
| StrCpy ${_RESULT} "Windows 10 21H2" | |
| Goto done | |
| IntCmp $0 ${WIN10_21H1} 0 +3 0 | |
| StrCpy ${_RESULT} "Windows 10 21H1" | |
| Goto done | |
| IntCmp $0 ${WIN10_20H2} 0 +3 0 | |
| StrCpy ${_RESULT} "Windows 10 20H2" | |
| Goto done | |
| IntCmp $0 ${WIN10_2004} 0 +3 0 | |
| StrCpy ${_RESULT} "Windows 10 2004" | |
| Goto done | |
| IntCmp $0 ${WIN10_1507} 0 not_supported 0 | |
| StrCpy ${_RESULT} "Windows 10" | |
| Goto done | |
| not_supported: | |
| StrCpy ${_RESULT} "Unsupported Windows Version" | |
| done: | |
| Pop $1 | |
| Pop $0 | |
| !macroend | |
| !define GetWindowsVersion "!insertmacro GetWindowsVersion" | |
| ;------------------------------------------------------------ | |
| ; GetWindowsArchitecture | |
| ; Returns x86, x64, or ARM64 | |
| ;------------------------------------------------------------ | |
| !macro GetWindowsArchitecture _RESULT | |
| Push $0 | |
| System::Call 'kernel32::GetNativeSystemInfo(*i16)i.r0' | |
| ${If} ${RunningX64} | |
| ; Check if ARM64 | |
| ReadRegStr $0 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PROCESSOR_ARCHITECTURE" | |
| ${If} $0 == "ARM64" | |
| StrCpy ${_RESULT} ${ARCH_ARM64} | |
| ${Else} | |
| StrCpy ${_RESULT} ${ARCH_X64} | |
| ${EndIf} | |
| ${Else} | |
| StrCpy ${_RESULT} ${ARCH_X86} | |
| ${EndIf} | |
| Pop $0 | |
| !macroend | |
| !define GetWindowsArchitecture "!insertmacro GetWindowsArchitecture" | |
| ;------------------------------------------------------------ | |
| ; RequireWindows10OrLater | |
| ; Shows error and quits if not Windows 10+ | |
| ;------------------------------------------------------------ | |
| !macro RequireWindows10OrLater | |
| Push $0 | |
| ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentMajorVersionNumber" | |
| ${If} $0 < 10 | |
| MessageBox MB_OK|MB_ICONSTOP "This application requires Windows 10 or later." | |
| Quit | |
| ${EndIf} | |
| Pop $0 | |
| !macroend | |
| !define RequireWindows10OrLater "!insertmacro RequireWindows10OrLater" | |
| ;------------------------------------------------------------ | |
| ; RequireWindows11OrLater | |
| ; Shows error and quits if not Windows 11+ | |
| ;------------------------------------------------------------ | |
| !macro RequireWindows11OrLater | |
| Push $0 | |
| ${IsWindows11} $0 | |
| ${If} $0 == 0 | |
| MessageBox MB_OK|MB_ICONSTOP "This application requires Windows 11 or later." | |
| Quit | |
| ${EndIf} | |
| Pop $0 | |
| !macroend | |
| !define RequireWindows11OrLater "!insertmacro RequireWindows11OrLater" | |
| ;------------------------------------------------------------ | |
| ; GetWindowsDisplayVersion | |
| ; Returns the display version (e.g., "23H2") | |
| ;------------------------------------------------------------ | |
| !macro GetWindowsDisplayVersion _RESULT | |
| ReadRegStr ${_RESULT} HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "DisplayVersion" | |
| ${If} ${_RESULT} == "" | |
| ReadRegStr ${_RESULT} HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "ReleaseId" | |
| ${EndIf} | |
| !macroend | |
| !define GetWindowsDisplayVersion "!insertmacro GetWindowsDisplayVersion" | |
| ;------------------------------------------------------------ | |
| ; IsWindows10LTSC | |
| ; Returns true if running Windows 10 LTSC/LTSB | |
| ;------------------------------------------------------------ | |
| !macro IsWindows10LTSC _RESULT | |
| Push $0 | |
| ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "EditionID" | |
| ${If} $0 == "Enterprise" | |
| ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "ProductName" | |
| StrCpy $0 $0 4 -4 ; Get last 4 chars | |
| ${If} $0 == "LTSC" | |
| ${OrIf} $0 == "LTSB" | |
| StrCpy ${_RESULT} 1 | |
| Goto done_ltsc | |
| ${EndIf} | |
| ${EndIf} | |
| StrCpy ${_RESULT} 0 | |
| done_ltsc: | |
| Pop $0 | |
| !macroend | |
| !define IsWindows10LTSC "!insertmacro IsWindows10LTSC" | |
| !endif ; MODERN_WINVER_NSH |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment