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.