Mendip Data Systems

Database applications for businesses and schools

LogoTransparent

Code Samples for Businesses, Schools & Personal Use

 

 

Access / Office 365 / Windows Version Check

Return to Code Samples Page

Version 2.2       Updated 18/12/2018              

 

Attached is a utility for checking the following:

a) Windows version & bitness (32/64-bit)

b) Access version & bitness

c) Whether Office 365 is installed

 

3 versions are provided (zipped) :      

1. ACCDB for Access 2010 or later                    

 

2. ACCDB version for Access 2007              

 

3. MDB version (Access 2000 format)  

 

Save this to a trusted location or click Enable Content

It will then automatically collect the info similar to that below.

It may take a few seconds to complete

 

A PDF Help file is included with each of the above but it can also be downloaded separately:

   Access/Windows/Office 365 Help (PDF)

Access&WindowsChecker

Click the image to view a larger version ...

 

Detecting Office 365 is more difficult because the same version numbering is used for both retail & subscription

versions of Access. Instead the code checks for a ClickToRun registry key - if it exists, you have Office 365.

 

For example, it looks for this key on pure 32-bit or pure 64-bit systems:

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\

  Microsoft\Office\16.0\Access Connectivity Engine\Engines

 

For 32-bit Office on 64-bit Windows, it looks for:

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\

  Wow6432Node\Microsoft\Office\16.0\Access Connectivity Engine\Engines

 

However, it is not that ‘simple’.

If a retail version of Office 2013/2016/2019 is installed but the user enters their Microsoft account information either during installation or at a later time, this triggers the ClickToRun registry structure to be created!

 

In other words, it is then treated as Office 365 even though it is still a retail product.

However, the software is not updated with new features as is the case with a true Office 365 product

 

CODE:

Several functions are avaialble for obtaining the Access version in varying degrees of detail.

 

- GetAccessVersion              e.g. 14.0 for Access 2010

- GetAccessBuildVersion      e.g. 14.0.7195 for Access 2010 SP2

- GetAccessEXEVersion        e.g.  Access 2010 SP2 14.0.7195

 

These are combined with another function IsOfficex64 which returns the value 32-bit or 64-bit

 

CODE:

 

Function GetAccessVersion()

   'get Access version number e.g. 14.0 for Access 2010

   GetAccessVersion = SysCmd(acSysCmdAccessVer)

End Function

 

'=======================================

 

Function GetAccessBuildVersion() As String

   'Gets full Access version number including program updates / service packs

   'e.g. 14.6024 for Access 2010 SP1

   GetAccessBuildVersion = Nz(SysCmd(acSysCmdAccessVer) & "." & SysCmd(715), "None") & " " & IsOfficex64

   'Debug.Print GetAccessBuildVersion

End Function

 

'=======================================

 

Function GetAccessEXEVersion() As String

 

   'Valid for use with Access 2000 or later.

   'Original version may have been by Tom van Stiphout

   

   On Error Resume Next

   Dim sAccessVerNo As String

   

   sAccessVerNo = SysCmd(acSysCmdAccessVer) & "." & SysCmd(715)

   

   Select Case sAccessVerNo

       'Access 2000

       Case "9.0.0.0000" To "9.0.0.2999": GetAccessEXEVersion = "Access 2000 " & sAccessVerNo & ""

       Case "9.0.0.3000" To "9.0.0.3999": GetAccessEXEVersion = "Access 2000 SP1 " & sAccessVerNo & ""

       Case "9.0.0.4000" To "9.0.0.4999": GetAccessEXEVersion = "Access 2000 SP2 " & sAccessVerNo & ""

       Case "9.0.0.6000" To "9.0.0.6999": GetAccessEXEVersion = "Access 2000 SP3 " & sAccessVerNo & ""

       

       'Access 2002

       Case "10.0.2000.0" To "10.0.2999.9": GetAccessEXEVersion = "Access 2002 " & sAccessVerNo & ""

       Case "10.0.3000.0" To "10.0.3999.9": GetAccessEXEVersion = "Access 2002 SP1 " & sAccessVerNo & ""

       Case "10.0.4000.0" To "10.0.4999.9": GetAccessEXEVersion = "Access 2002 SP2 " & sAccessVerNo & ""

       

       'Access 2003

       Case "11.0.0000.0" To "11.0.5999.9999": GetAccessEXEVersion = "Access 2003 " & sAccessVerNo & ""

       Case "11.0.6000.0" To "11.0.6999.9999": GetAccessEXEVersion = "Access 2003 SP1 " & sAccessVerNo & ""

       Case "11.0.7000.0" To "11.0.7999.9999": GetAccessEXEVersion = "Access 2003 SP2 " & sAccessVerNo & ""

       Case "11.0.8000.0" To "11.0.8999.9999": GetAccessEXEVersion = "Access 2003 SP3 " & sAccessVerNo & ""

       

       'Access 2007

       Case "12.0.0000.0" To "12.0.5999.9999": GetAccessEXEVersion = "Access 2007 " & sAccessVerNo & ""

       Case "12.0.6211.0" To "12.0.6422.9999": GetAccessEXEVersion = "Access 2007 SP1 " & sAccessVerNo & ""

       Case "12.0.6423.0" To "12.0.9999.9999": GetAccessEXEVersion = "Access 2007 SP2 " & sAccessVerNo & ""

       

       'Access 2010

       Case "14.0.0000.0000" To "14.0.6022.1000": GetAccessEXEVersion = "Access 2010 " & sAccessVerNo & ""

       Case "14.0.6023.1000" To "14.0.7014.9999": GetAccessEXEVersion = "Access 2010 SP1 " & sAccessVerNo & ""

       Case "14.0.7015.1000" To "14.0.9999.9999": GetAccessEXEVersion = "Access 2010 SP2 " & sAccessVerNo & ""

       

       'Access 2013

       Case "15.0.0000.0000" To "15.0.4569.1505": GetAccessEXEVersion = "Access 2013 " & sAccessVerNo & ""

       Case "15.0.4569.1506" To "15.0.9999.9999": GetAccessEXEVersion = "Access 2013 SP1 " & sAccessVerNo & ""

       

        'Access 2016/2019/365

       Case "16.0.0000.0000" To "16.0.99999.9999"

           Select Case CInt(Mid(sAccessVerNo, 6))

           

           'A2019 started at approx 16.0.10827.20138

           Case Is < 10827

               GetAccessEXEVersion = "Access 2016 " & sAccessVerNo & ""

           Case Else

               GetAccessEXEVersion = "Access 2019 " & sAccessVerNo & ""

           End Select

       

       Case Else

       GetAccessEXEVersion = "Access - Unknown Version"

       

   End Select

   

   If SysCmd(acSysCmdRuntime) Then GetAccessEXEVersion = GetAccessEXEVersion & " Run-time"

   

   GetAccessEXEVersion = GetAccessEXEVersion & " " & IsOfficex64

   

  ' Debug.Print GetAccessEXEVersion

End Function

 

'=======================================

 

Function IsOfficex64()

  'checks if Office is 32 or 64 bit

 

 #If Win64 Then

    IsOfficex64 = "64-bit"

 #Else

    IsOfficex64 = "32-bit"

 #End If

 

 'Debug.Print IsOfficex64

 

End Function

To obtain the Windows version and bitness, the following code is used:

 

CODE:

 

Public Function GetOperatingSystem()

   Dim localHost       As String

   Dim objWMIService   As Variant

   Dim colOperatingSystems As Variant

   Dim objOperatingSystem As Variant

 

   On Error GoTo Err_Handler

 

   localHost = "." 'Technically could be run against remote computers, if allowed

   Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & localHost & "\root\cimv2")

   Set colOperatingSystems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")

 

   For Each objOperatingSystem In colOperatingSystems

       GetOperatingSystem = objOperatingSystem.Caption & " " & objOperatingSystem.Version

     '  Exit Function

   Next

 

  ' Debug.Print GetOperatingSystem

   

   'Determine if operating system is 32-bit or 64-bit

   '-------------------------------------------------

   GetOperatingSystem = GetOperatingSystem & " " & IsWin32OrWin64

   

   'Debug.Print GetOperatingSystem

   

Exit_Handler:

  ' On Error Resume Next

   Exit Function

 

Err_Handler:

   FormattedMsgBox "Error " & Err.Number & " in GetOperatingSystem procedure :             " & _

       "@" & Err.Description & "            @", vbCritical, "Program error"

   Resume Exit_Handler

End Function

 

'=======================================

 

Function IsWin32OrWin64()

 

  'Determine if operating system is 32-bit or 64-bit

   '-------------------------------------------------

   'Modified from code provided at:

   '  http://www.vb-helper.com/howto_get_os_name.html

   Dim proc_query As String

   Dim proc_results As Object

   Dim Info As Object

   

   proc_query = "SELECT * FROM Win32_Processor"

   Set proc_results = GetObject("Winmgmts:").ExecQuery(proc_query)

   For Each Info In proc_results

       IsWin32OrWin64 = Info.AddressWidth & "-bit"

   Next Info

   

   'Debug.Print IsWin32OrWin64

 End Function

 

 Function CheckAccess365() As Boolean

 

 On Error GoTo Err_Handler

   

   'If Access version <16.0 then NOT A365

   'However in case of dual Office installation, this step will be bypassed

 '  If CInt(GetAccessVersion) < 16 Then

 '      CheckAccess365 = False

 '       Debug.Print "Access 365 : " & CheckAccess365

 '        Exit Function

 '  End If

   

   'Check Windows bitness

   If IsWin32OrWin64 = "32-bit" Then

           registryKey = "SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Microsoft\Office\16.0\" & _

                                          "Access Connectivity Engine\Engines"

   Else '64-bit Windows

       'check Office bitness

       If IsOfficex64 = "32-bit" Then

          'check in Wow6432Node

           registryKey = "SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Wow6432Node\" & _

                                           "Microsoft\Office\16.0\Access  Connectivity Engine\Engines"

       Else '64-bit Office

           registryKey = "SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Microsoft\Office\16.0\" & _

                                           "Access Connectivity Engine\Engines"

       End If

   End If

   

   KeyName = "SystemDB" 'look for specific string value

   

   ' check string value exists in registry

    If GetStringValFromRegistry(HKEY_LOCAL_MACHINE, registryKey, KeyName) <> "" Then

           CheckAccess365 = True

   End If

   

  ' Debug.Print "Access 365 : " & CheckAccess365

   

 Exit_Handler:

      Exit Function

   

 Err_Handler:

     MsgBox "Error " & Err.Number & " in CheckAccess365 procedure: " & Err.Description

     Resume Exit_Handler

 End Function

NOTE:

 

I have successfully tested the Office365 code on several PCs with:

- Windows/Access both 32-bit

- Windows/Access both 64-bit

- 64-bit Windows & 32-bit Access

- dual installation of Access 2010 & Access 365 (as in the screenshot above)

 

Many thanks to several other users who tested this on their own computer systems.

Particular thanks are due to Utter Access forum member Jeff Holm for repeatedly testing different versions in 'mixed bitness' systems and for helping to solve issues related to reading the Wow6432Node registry area

 

Despite the extensive testing already done, it is possible that some Office365 users may have different registry keys to those being referenced. If so, the code will NOT detect Office 365

 

I would be grateful for feedback from any Office 365 users who find that the check does not work correctly

If that is the case, please email me with the following information:

 

a) Access/Windows versions & bitnesses

b) the full registry key path in HKEY_LOCAL_MACHINE containing the ClickToRun key for the

   Access Connectivity Engines\Engines folder

 

 Public Function GetStdRegProv() As Object

  ' http://msdn.microsoft.com/en-us/library/aa394600(VS.85).aspx

  'code updated by Jeff Holm to manage mixed mode systems

 

 On Error GoTo ErrHandler:

   

   Dim strComputer As String

 

   strComputer = "."

   

   If IsWin32OrWin64 = IsOfficex64 Then    'Office & Windows bitness match, no need to force 64-bit

 

       Set GetStdRegProv = GetObject("winmgmts:" _

                                   & "{impersonationLevel=impersonate}!\\" _

                                   & strComputer & "\root\default:StdRegProv")

                                   

   Else    'Office 32-bit & Windows 64-bit, so have to elevate GetStdRegProv to 64-bit

 

       Dim objCtx As Object

       Dim objLocator As Object

       Dim objServices As Object

       Dim objStdRegProv As Object

 

       Set objCtx = CreateObject("WbemScripting.SWbemNamedValueSet")

       objCtx.Add "__ProviderArchitecture", 64

       objCtx.Add "__RequiredArchitecture", True

       Set objLocator = CreateObject("Wbemscripting.SWbemLocator")

       Set objServices = objLocator.ConnectServer(strComputer, "root\default", "", "", , , , objCtx)

       Set GetStdRegProv = objServices.Get("StdRegProv")

 

       Set objServices = Nothing

       Set objLocator = Nothing

       Set objCtx = Nothing

   End If

   

 Exit_ErrHandler:

   On Error Resume Next

   Exit Function

   

 ErrHandler:

   If Err.Number >= 0 Then

       MsgBox "Error " & Err.Number & " in GetStdRegProv procedure: " & Err.description, vbOKOnly + vbCritical

   End If

   Resume Exit_ErrHandler

   

 End Function

When using 32-bit applications in 64-bit Windows, registry entries are made to the Wow6432Node.

Windows uses a process called registry redirection to manage this area.

However, that causes issues when trying to view those entries from a 32-bit application such as Access.

 

This area cannot be read from or written to using standard code as used on ’pure’ 32-bit or 64-bit systems.

Instead, I have used ‘special’ code which is elevated to 64-bit as and when required

A JET ShowPlan Manager application is also available which includes the functions used in this utility.

 

Its purpose is to manage the registry settings needed to enable the JET ShowPlan feature and view the execution plans of Access queries and SQL statements.