Solved VBScript to determine bitness of local MS Access version (1 Viewer)

AOB

Registered User.
Local time
Today, 08:58
Joined
Sep 26, 2012
Messages
613
Hi there,

I've run into some difficulties with a distributed Access DB (that is, a central ACCDB backend with distributed ACCDE frontends) The front end utilises some API's which obviously have to be declared differently in the two configurations (made pointer-safe in 64-bit) and I've discovered that even if I build the ACCDE on a 32-bit machine, there are issues when trying to open it on a 64-bit machine (and vice versa) My guess is that the issue lies with the fact that ACCDE's are pre-compiled, executable-only files (whereas ACCDB's are compiled at run-time) therefore whichever version of Access you build the ACCDE in, will not work in a conflicting configuration.

In other words, even if you conditionalise the declarations, i.e. :

Code:
#If VBA7 Then
    Private Declare PtrSafe Sub GetSystemInfo Lib "kernel32" (lpSystemInfo As SYSTEM_INFO)
#Else
    Private Declare Sub GetSystemInfo Lib "kernel32" (lpSystemInfo As SYSTEM_INFO)
#End If

...because the ACCDE is already pre-compiled when the user goes to run it, if their configuration doesn't match that of the version that did the compile, it's not going to work.

As luck would have it, as a rule, I use a launch script on the server; users have a local shortcut which points to the script which pulls down the latest version of the front-end to their local device and runs it. I've always used this model as it's a handy way of distributing updates without having to push new versions to each users device.

My plan (and feel free to tell me I'm barking up a wrong tree here) is to build two versions of the same fundamental ACCDE, one on a 32-bit machine (with 32-bit-safe declarations) and another on a 64-bit machine (with 64-bit-safe declarations) and host both versions on the network. And then modify that launch script so that when the user runs it, the script can determine the bitness of the local version of Access (32-bit or 64-bit) and pull down the version of the ACCDE that is appropriate for their local version (thus circumventing the pre-compile problem)

I was going to simply check the Office version and run the 32-bit version for v15.x / Office 2013 or below, and the 64-bit version for v16.x / M365 and above (by querying WMI Service with Select * from CIM_Datafile Where against the app paths returned from the registry via both HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths\MSACCESS.EXE and HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\App Paths\MSACCESS.EXE)

But I'm trying to do this as robustly as possible (i.e. a catch-all solution that can be used as a template for other DB's) and I'm conscious that you can have 64-bit configurations of earlier versions and, indeed, 32-bit versions of later versions (even though, I think, in my particular case, these are rare, if indeed possibly non-existent)

So - very long-winded way of asking...

Does anybody know a good way, via VB Script, of determining the bitness of the locally installed version of Access (as opposed to simply the major version) ?

Thanks

AOB
 

Ranman256

Well-known member
Local time
Today, 04:58
Joined
Apr 9, 2015
Messages
4,337
paste into a module . Usage: msgbox Is64Bit()


Code:
Public Function Is64bit() As Boolean
    #If Win64 Then
      Is64bit = True
    #Else
      Is64bit = False
    #End If
End Function
 
  • Like
Reactions: AOB

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 16:58
Joined
May 7, 2009
Messages
19,169
vscript sample:
Code:
   Dim shell, GetOSBits, oAccess
   Dim path
   Set shell = CreateObject("WScript.Shell")
   If shell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITECTURE%") = "AMD64" Then
      GetOsBits = "64"
   Else
      GetOsBits = "32"
   End If
   Set shell=Nothing
   Set oAccess = CreateObject("Access.Application")
   path = oAccess.syscmd(9)
   oAccess.Quit
   set oAccess=Nothing
 
   wscript.echo GetOSBits
   wscript.echo path

   If GetOSBits = "64" And Instr(1, path,"Program Files (x86)") = 0 Then
      wscript.echo "Office is x64"
   else
      wscript.echo "Office is x86"
   end if
 
Last edited:
  • Like
Reactions: AOB

AOB

Registered User.
Local time
Today, 08:58
Joined
Sep 26, 2012
Messages
613
paste into a module . Usage: msgbox Is64Bit()


Code:
Public Function Is64bit() As Boolean
    #If Win64 Then
      Is64bit = True
    #Else
      Is64bit = False
    #End If
End Function
Thanks @Ranman256 but this is VBA, not VBScript - VBA not an option as I need to determine the bitness before I launch the ACCDE
 

AOB

Registered User.
Local time
Today, 08:58
Joined
Sep 26, 2012
Messages
613
vscript sample:
Code:
   Dim shell, GetOSBits, oAccess
   Dim path
   Set shell = CreateObject("WScript.Shell")
   If shell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITECTURE%") = "AMD64" Then
      GetOsBits = "64"
   Else
      GetOsBits = "32"
   End If
   Set shell=Nothing
   Set oAccess = CreateObject("Access.Application")
   path = oAccess.syscmd(9)
   oAccess.Quit
   set oAccess=Nothing

   wscript.echo GetOSBits
   wscript.echo path

   If GetOSBits = "64" And Instr(1, path,"Program Files (x86)") = 0 Then
      wscript.echo "Office is x64"
   else
      wscript.echo "Office is x86"
   end if
Thanks @arnelgp - this seems to work pretty well!

I made one modification as I don't particularly want to launch Access (in order to determine the path to the MSACCESS.EXE), then exit and relaunch Access again - so I subbed that part out and replaced it with a registry read :

Code:
Set objShell = WScript.CreateObject("WScript.Shell")

strProcessorArchitecture = objShell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITECTURE%")
If strProcessorArchitecture = "AMD64" Then
    strOSBitness = "64"
Else
    strOSBitness = "32"
End If
    
strRegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\MSACCESS.EXE\Path"
strMSAccessExePath = objShell.RegRead(strRegKey) & "MSACCESS.EXE"

If strOSBitness = "64" And Instr(1, strMSAccessExePath, "Program Files (x86)") = 0 Then
    ' 64-bit version of MS Access is installed locally - copy over the 64-bit compiled version
    strNetworkFileName = strNetworkFileName64
Else
    ' 32-bit version of MS Access is installed locally - copy over the 32-bit compiled version
    strNetworkFileName = strNetworkFileName32
End If
 

theDBguy

I’m here to help
Staff member
Local time
Today, 01:58
Joined
Oct 29, 2018
Messages
21,357
Thanks @arnelgp - this seems to work pretty well!

I made one modification as I don't particularly want to launch Access (in order to determine the path to the MSACCESS.EXE), then exit and relaunch Access again - so I subbed that part out and replaced it with a registry read :

Code:
Set objShell = WScript.CreateObject("WScript.Shell")

strProcessorArchitecture = objShell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITECTURE%")
If strProcessorArchitecture = "AMD64" Then
    strOSBitness = "64"
Else
    strOSBitness = "32"
End If
   
strRegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\MSACCESS.EXE\Path"
strMSAccessExePath = objShell.RegRead(strRegKey) & "MSACCESS.EXE"

If strOSBitness = "64" And Instr(1, strMSAccessExePath, "Program Files (x86)") = 0 Then
    ' 64-bit version of MS Access is installed locally - copy over the 64-bit compiled version
    strNetworkFileName = strNetworkFileName64
Else
    ' 32-bit version of MS Access is installed locally - copy over the 32-bit compiled version
    strNetworkFileName = strNetworkFileName32
End If
Just FYI, if it's ever possible that a user would have a C2R version of Access installed, you might want to add a test for that also. Cheers!
 
  • Like
Reactions: AOB

AOB

Registered User.
Local time
Today, 08:58
Joined
Sep 26, 2012
Messages
613
Just FYI, if it's ever possible that a user would have a C2R version of Access installed, you might want to add a test for that also. Cheers!
Very good point! I don't think Click-To-Run is used much here but I shall file this in the "Maybe" column for the next time it falls over! 😵🤪
 

IbrBadri

Member
Local time
Today, 10:58
Joined
May 24, 2020
Messages
35
Very good point! I don't think Click-To-Run is used much here but I shall file this in the "Maybe" column for the next time it falls over! 😵🤪
could you or other share the solution steps, so me and all others searching for this article solution can benefit from it.

Thanks in advance
 

Gasman

Enthusiastic Amateur
Local time
Today, 08:58
Joined
Sep 21, 2011
Messages
14,037
could you or other share the solution steps, so me and all others searching for this article solution can benefit from it.

Thanks in advance
Isn't that the code in post #5 ? :unsure:
 
Local time
Today, 09:58
Joined
Feb 27, 2023
Messages
43
VBS using ProductCode:
Code:
With CreateObject("Access.Application")
    If Mid(.ProductCode, 21, 1) = 0 Then
        wscript.echo "Office is x86 ProductCode is " & .ProductCode
    Else
        wscript.echo "Office is x64 ProductCode is " & .ProductCode
    End If
End With
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 03:58
Joined
Feb 28, 2001
Messages
26,996
If YOU are the distributor of the .ACCDE files in question, do yourself a favor. Define a User-Defined Property (UDP) when you create the .ACCDE files and then your scripts can look for your UDP to see which one it is.


If you are not the creator of the scripts, but have the ability to add a UDP to the extant file, that would also work. If you don't create the scripts AND cannot add the property, then one of the other methods mentioned in the threads might be required.
 

isladogs

MVP / VIP
Local time
Today, 08:58
Joined
Jan 14, 2017
Messages
18,186
Here's another utility to get full details of the Access/Office version & bitness together with the same info for Windows

1680705579244.png



However, its an ACCDE file so the code isn't accessible
 

IbrBadri

Member
Local time
Today, 10:58
Joined
May 24, 2020
Messages
35
If YOU are the distributor of the .ACCDE files in question, do yourself a favor. Define a User-Defined Property (UDP) when you create the .ACCDE files and then your scripts can look for your UDP to see which one it is.


If you are not the creator of the scripts, but have the ability to add a UDP to the extant file, that would also work. If you don't create the scripts AND cannot add the property, then one of the other methods mentioned in the threads might be required.
Thanks for your help,

Yes I distribute the .accde files (front end and back end) since long time.

Each time I upgrade a system I should create 2 .accde files for the users 32bit and 64bit with it's long process of protecting each file.

I am using office 2016 64bit and VBA with a limited knowledge and still learning on the VBA.

So I am confused about steps of putting and calling these codes in the right places.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 03:58
Joined
Feb 28, 2001
Messages
26,996
You would put the properties on the files MANUALLY when you create the two files you want. Pick a standard property that is empty OR add a new property according to the link I gave you earlier.

You can check the properties using VBA according to this link:


Since VBS also has the ability to use the file system object, you could use FSO to do a GetFile of the file in question after which you can examine its properties.

Another thing to consider, though, is that you are copying a file based on the user's 32-bit or 64-bit version of Access, right? Use one of the earlier methods from this thread to decide which version of Access you need. Build your two files with the suffix of _32 or _64 on the name you really wanted. Like MYDB_32 and MYDB_64 ... then copy down the file with correct bitness based on its name. Then RENAME it in place from MYDB_32 (or MYDB_64) to MYDB. Then you don't even need file attributes. Just pick the right name and there you go.
 

IbrBadri

Member
Local time
Today, 10:58
Joined
May 24, 2020
Messages
35
Thanks The_Doc_Man for your kind interest to help me.
Although it's some how difficult for me to understand your level of explaining's, but I am on going to learn thease steps.

Yes, I am already doing both 32bit and 64bit *.accde files by the simple way:-
1- Copying my master file to two files named FE64bit.accdb and FE32bit.accdb
2- On my pc (64bit) I do the security tasks and save the file FE64bit.accdb as FE64bit.accde.
3- On User pc (32bit) I repeat the security tasks and save file FE32bit.accdb as FE32bit.accde.
that's all.

What I thought; this threat shall help me solve repeating the above tasks of securites and save one file containg this codes as FE.accde and will work on both 32bit and 64bit.

Otherwise; with my limited experince on VBA, why doing all this codes for?
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 03:58
Joined
Feb 28, 2001
Messages
26,996
OK, I may sometimes get a little bit lost here. I am responding now, specifically, to this:

As luck would have it, as a rule, I use a launch script on the server; users have a local shortcut which points to the script which pulls down the latest version of the front-end to their local device and runs it. I've always used this model as it's a handy way of distributing updates without having to push new versions to each users device.

My plan (and feel free to tell me I'm barking up a wrong tree here) is to build two versions of the same fundamental ACCDE, one on a 32-bit machine (with 32-bit-safe declarations) and another on a 64-bit machine (with 64-bit-safe declarations) and host both versions on the network. And then modify that launch script so that when the user runs it, the script can determine the bitness of the local version of Access (32-bit or 64-bit) and pull down the version of the ACCDE that is appropriate for their local version (thus circumventing the pre-compile problem)

OK, if you manually build your FE64 and FE32 versions named as such, then when this script runs, it only has a few things to do.

1. Determine which version of Access is available on the machine you are about to use. Other responders have offered several ways of doing this.
2. Based on the bitness you discover in step 1, copy either the FE64 or FE32 version to the user's local working folder.
3. Rename the version you downloaded from FE64 or FE32 to FE.
4. Launch the FE file.

The codes that others have shown you relate to determining the bitness of Access. If you already have a launcher script to pull down the latest version of the FE file, just modify the stop that does the COPY to pick the FE file of the correct bitness. Then add the RENAME step in the script, and the source name is just the name of the FE file you copied. The destination of the RENAME is whatever you use for the FE name. Then you just launch the FE file by its "common" name. And, at this point, if your user manually tries to launch the file after this script runs, it has the right one in the user's working folder, so you are good to go.

I was not addressing the issue of whether you can build a single version that would work correctly on both machines. I suspect you cannot because an .ACCDE is already "compiled" so that any conditional compilation has taken effect. Moving that file to two different bitness machines would require the compilation to occur upon opening the FE file, and the DE file can't do that. (It's already too late.)

Does that help clarify what is going on?
 

IbrBadri

Member
Local time
Today, 10:58
Joined
May 24, 2020
Messages
35
OK, I may sometimes get a little bit lost here. I am responding now, specifically, to this:



OK, if you manually build your FE64 and FE32 versions named as such, then when this script runs, it only has a few things to do.

1. Determine which version of Access is available on the machine you are about to use. Other responders have offered several ways of doing this.
2. Based on the bitness you discover in step 1, copy either the FE64 or FE32 version to the user's local working folder.
3. Rename the version you downloaded from FE64 or FE32 to FE.
4. Launch the FE file.

The codes that others have shown you relate to determining the bitness of Access. If you already have a launcher script to pull down the latest version of the FE file, just modify the stop that does the COPY to pick the FE file of the correct bitness. Then add the RENAME step in the script, and the source name is just the name of the FE file you copied. The destination of the RENAME is whatever you use for the FE name. Then you just launch the FE file by its "common" name. And, at this point, if your user manually tries to launch the file after this script runs, it has the right one in the user's working folder, so you are good to go.

I was not addressing the issue of whether you can build a single version that would work correctly on both machines. I suspect you cannot because an .ACCDE is already "compiled" so that any conditional compilation has taken effect. Moving that file to two different bitness machines would require the compilation to occur upon opening the FE file, and the DE file can't do that. (It's already too late.)

Does that help clarify what is going on?
Yes, thanks for clarifying the point.

I understood the needs of this VBA codes, specially for continuing FE upgrades for many user's without looking whats version they are using or changing their FE file.

In my case systems is for "Info Mng and Acc Sys" which is not require continuous upgrades except after years when they need to add/modify reports or adding a new data fields, and I put the 32FE and 64FE on a server shared folder, user's copying the FE worked on their machine. both files linked to the server data BE file, so I used to do that simple way.

Thanks again for your patience.
 

Users who are viewing this thread

Top Bottom