VBA – Get Windows 10 Version and Build Numbers

I’ve been trying to get more information as part of my error handler and part of that would be to gather information about the OS itself similar to what we can get from the WinVer command.

Microsoft Windows 10 Home
Version 22H2 (OS Build 19045.5011)

Breaking Each Property Down Separately

As such, I’ve devised a couple simple functions to retrieve the Windows Version Number and Build Number.

VBA Function To Retrieve The Windows Product Name

'---------------------------------------------------------------------------------------
' Procedure : OS_ProductName
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Retrieve the Windows OS Product Name
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Late Binding  -> none required
'
' Usage:
' ~~~~~~
' ? OS_ProductName
'   Returns -> Windows 10 Home
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2020-12-23              Initial Release
'---------------------------------------------------------------------------------------
Public Function OS_ProductName() As String
    On Error GoTo Error_Handler
    Dim oShell                As Object
    Dim sRegKey               As String

    Set oShell = CreateObject("WScript.Shell")
    sRegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName"
    OS_ProductName = oShell.RegRead(sRegKey)

Error_Handler_Exit:
    On Error Resume Next
    Set oShell = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: OS_ProductName" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occured!"
    Resume Error_Handler_Exit
End Function

VBA Function To Retrieve The Windows Version Number

'---------------------------------------------------------------------------------------
' Procedure : OS_Version
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Retrieve the Windows OS Version No.
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Late Binding  -> none required
'
' Usage:
' ~~~~~~
' ? OS_Version
'   Returns -> 22H2
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2020-12-23              Initial Release
' 2         2024-10-16              Update to return the version per the WinVer command
'---------------------------------------------------------------------------------------
Public Function OS_Version() As String
    On Error GoTo Error_Handler
    Dim oShell                As Object
    Dim sRegKey               As String

    Set oShell = CreateObject("WScript.Shell")
    sRegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DisplayVersion"
    OS_Version = oShell.RegRead(sRegKey)

Error_Handler_Exit:
    On Error Resume Next
    Set oShell = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: OS_Version" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occured!"
    Resume Error_Handler_Exit
End Function

VBA Function To Retrieve The Windows Build Number

'---------------------------------------------------------------------------------------
' Procedure : OS_BuildNo
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Retrieve the Windows OS Build No. (Windows 10)
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Late Binding  -> none required
'
' Usage:
' ~~~~~~
' ? OS_BuildNo
'   Returns -> 18363.1256
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2020-12-23              Initial Release
'---------------------------------------------------------------------------------------
Public Function OS_BuildNo() As Double
    On Error GoTo Error_Handler
    Dim oShell                As Object
    Dim sRegKey               As String
    Dim lBuild                As Long
    Dim lBuildDecimals        As Long

    Set oShell = CreateObject("WScript.Shell")
    sRegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentBuildNumber"
    lBuild = oShell.RegRead(sRegKey)
    sRegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\UBR"
    lBuildDecimals = oShell.RegRead(sRegKey)
    OS_BuildNo = CDbl(lBuild & "." & lBuildDecimals)

Error_Handler_Exit:
    On Error Resume Next
    Set oShell = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: OS_BuildNo" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occured!"
    Resume Error_Handler_Exit
End Function

Doing It In One Go

Another approach could be to gather all the information as part of a single procedure. We can achieve this by creating a generic registry reading function and then building a procedure to get all the property values in one shot.

Generic Registry Value Reading Function

'---------------------------------------------------------------------------------------
' Procedure : Registry_Read
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Retrieve the data of a registry key's value
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Late Binding  -> none required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sKey      : Registry key to looking in
' sValue    : Value to retrieve the data of
'
' Usage:
' ~~~~~~
' ? Registry_Read("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "ProductName")
'   Returns -> Windows 10 Home
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2004-07-22              Initial Release
' 2         2024-10-16              Updated Error Handler and Header
'---------------------------------------------------------------------------------------
Public Function Registry_Read(sKey, sValue) As Variant
On Error GoTo Error_Handler
    On Error Resume Next
    Dim oShell                As Object

    Set oShell = CreateObject("WScript.Shell")
    Registry_Read = oShell.RegRead(sKey & sValue)
    
Error_Handler_Exit:
    On Error Resume Next
    Set oShell = Nothing
    Exit Function
 
Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Source: Registry_Read" & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

Windows Information Gathering Procedure

'---------------------------------------------------------------------------------------
' Procedure : GetWindowsInfo
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Returns various Windows OS properties to the calling procedure
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: None required
' Dependencies: Registry_Read()
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sWindowName       : A variable to hold the OS Product Name value
' sWindowsVersion   : A variable to hold the OS Version value
' sWindowBuild      : A variable to hold the OS build Number value
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2024-10-16              Initial Release
'---------------------------------------------------------------------------------------
Public Sub GetWindowsInfo(ByRef sWindowName As String, _
                          ByRef sWindowsVersion As String, _
                          ByRef sWindowBuild As String)
On Error GoTo Error_Handler

    sWindowName = Registry_Read("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "ProductName")
    sWindowsVersion = Registry_Read("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "DisplayVersion")
    sWindowBuild = Registry_Read("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "CurrentBuildNumber") & _
                   "." & Registry_Read("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "UBR")
    
Error_Handler_Exit:
    On Error Resume Next
    Exit Sub
 
Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Source: GetWindowsInfo" & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Sub

and then we could use this procedure by doing something like:

Sub GetWindowsInfo_Test()
    Dim sWindowName           As String
    Dim sWindowsVersion       As String
    Dim sWindowBuild          As String

    Call GetWindowsInfo(sWindowName, sWindowsVersion, sWindowBuild)
    Debug.Print "Microsoft " & sWindowName
    Debug.Print "Version " & sWindowsVersion & " (OS Build " & sWindowBuild & ")"
End Sub

which will output something similar to:

Microsoft Windows 10 Home
Version 22H2 (OS Build 19045.5011)

A Final Word

As you can see, nothing very difficult, it’s just a case of figuring out the proper registry key to read. Also note, there are other key/values available to us to get other information like: RegisteredOrganization, RegisteredOwner, …

Using a generic registry function is the smarter way to work and can help with other coding requirements that may arise down the road. That said, I strongly urge you to implement Self Healing Object Variables for any of these functions for the CreateObject(“WScript.Shell”) object variable to optimize performance.

If you want to also get the OS bitness (32 or 64-bit) then look at my article VBA – Determine OS Bitness

I hope this helps a few of you out there.