Skip to content

Instantly share code, notes, and snippets.

@daemondevin
Created November 3, 2025 08:11
Show Gist options
  • Select an option

  • Save daemondevin/e6a7199e1c625a52bfbf5b07c73b76de to your computer and use it in GitHub Desktop.

Select an option

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
; 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