32 Bit Issue (1 Viewer)

Tupacmoche

Registered User.
Local time
Today, 05:36
Joined
Apr 28, 2008
Messages
291
Hi All

My version of Access is 32 bit. When certain users try to access it using a Citrix server they get this error:

Your Microsoft Access database or project contains a missing or broken reference to the file 'MSCOMCTL.OCX' VERSION 2.2. When they click OK this msg comes up:

Compile error: The code in this project must be updated for use on 64-bit systems. Please review and update Declare statements and then mark them with the PtrSafe attribute. Finally this code is highlighted in the VBA editor:

Private Declare Function apiGetUserName Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long


Can anyone tell me what, I need to do to get this to work in the Citrix environment. I guess this would happen on any version of Access that is 64 bit.:banghead:
 

theDBguy

I’m here to help
Staff member
Local time
Today, 02:36
Joined
Oct 29, 2018
Messages
21,477
Hi. Just as a quick test, try modifying it to this:
Code:
Private Declare PtrSafe Function apiGetUserName Lib "advapi32.dll" Alias _
 "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long


Edit: Sorry, forgot to add PtrSafe earlier.
 
Last edited:

Tupacmoche

Registered User.
Local time
Today, 05:36
Joined
Apr 28, 2008
Messages
291
That code is exactly what I sent and have.
 

theDBguy

I’m here to help
Staff member
Local time
Today, 02:36
Joined
Oct 29, 2018
Messages
21,477
That code is exactly what I sent and have.
Sorry, somebody called for me and didn't quite finish doing what I wanted to do. The above post has been updated. Thanks.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 04:36
Joined
Feb 28, 2001
Messages
27,194
The question is, does the Citrix server have its own version of Access installed? Or did you actually develop using the facilities of the Citrix server?
 

Tupacmoche

Registered User.
Local time
Today, 05:36
Joined
Apr 28, 2008
Messages
291
The Citrix server has a 64 bit copy of Access installed.
 

Tupacmoche

Registered User.
Local time
Today, 05:36
Joined
Apr 28, 2008
Messages
291
I don't know if MSCOMCTL.OCX is discontinued but it is part of the error msg.
 

Tupacmoche

Registered User.
Local time
Today, 05:36
Joined
Apr 28, 2008
Messages
291
I have added this code but, am still getting a missing lib ref error msg.


#If Win64 Then
Private Declare PtrSafe Function apiGetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As LongLong) As LongLong
#Else
Private Declare PtrSafe Function apiGetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long
#End If


What library is missing? :banghead:
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 04:36
Joined
Feb 28, 2001
Messages
27,194
Here is the problem: You have a 32-bit app running on the Citrix copy of a 64-bit utility. Citrix will run the shared app that it has in its Programs folder. As you note in your posts, you KNOW that you have a 64-bit office. To make this work, particularly with Citrix, you have an uphill battle.

First, you have to determine whether you are going to be required to use the 64-bit version of Office because of other users not using Access but who ARE using other 64-bit Office programs.

If ANY users are doing so, you face the problem of having to have both "bitnesses" active at the same time. I've never seen that work.

If nobody is using Office except for you and your users, you MIGHT be able to persuade the Citrix manager to remove the 64-bit Office and replace it with the 32-bit Office. They are distributed on the same disk, so as long as Office was installed from a CD/DVD, you should be able to do the remove and install.

THEN you run into the technical issue, more of a concern for your Citrix manager than for you, that the Office version needs to have a multi-user license if you are going to share via Citrix. The EULA for Office off-the-shelf specifically says it is a single-user version.

THEN you run into the technical issue that your users will need some private storage on the Citrix server because otherwise they would be sharing the same FE file (or worse, the same whole database), which is how you get serious corruption issues. Search this forum for articles on Citrix use. Running from Citrix IS possible but is fraught with perils caused by sharing the unshareable.

FINALLY, if you are forced to work within the 64-bit Access, this article might help regarding how to manage that COMCTL library...

https://answers.microsoft.com/en-us...ndencies/4ae4dfc4-4a67-4927-990e-489cdb070efb

BUT... for a 32-bit app running with a 64-bit Access version, there is potential for a LOT of headaches because not all 32-bit libraries are compatible with 64-bit Office. And Microsoft has not so far shown any intentions of fixing that problem. Which means that when you installed 64-bit office, you only got the libraries that HAD been converted. And there is no telling exactly which libraries haven't made it over. Whereas if you had the ability to get to the 32-bit version, you would probably be able to see all of the familiar libraries.
 

Micron

AWF VIP
Local time
Today, 05:36
Joined
Oct 20, 2018
Messages
3,478
I've oft read that ActiveX controls are problematic in that they become deprecated from newer versions, so I've always stayed away from them. That may be the primary problem. Some users may no longer have that library.

Not being a Citrix expert, I can only recall using it from home to access db's that were on a shared network drive - the same one I would have used if I was at work. The suggestion seems to be that Access files must be on a Citrix server, which isn't what I think I was dealing with.
 

isladogs

MVP / VIP
Local time
Today, 10:36
Joined
Jan 14, 2017
Messages
18,239
@Tupacmoche
Back in post #9 you wrote
I don't know if MSCOMCTL.OCX is discontinued but it is part of the error msg.

The old Microsoft Windows Common Controls library, MSCOMCTL.OCX is not included in the list of available references with 32-bit Windows 10 though it can be added to the list.
However, from memory it is NOT installed with 64-bit Windows and if you install it you have to register it to get it to work.
Here’s another link that may be useful: https://www.urtech.ca/2017/11/solved-mscomctl-ocx-download-register-64-bit-windows/

My advice would be to remove that reference, and modify code if necessary to prevent it being an issue

From post #11
I have added this code but, am still getting a missing lib ref error msg.

#If Win64 Then
Private Declare PtrSafe Function apiGetUserName Lib "advapi32.dll" Alias
"GetUserNameA" (ByVal lpBuffer As String, nSize As LongLong) As LongLong
#Else
Private Declare PtrSafe Function apiGetUserName Lib "advapi32.dll" Alias
"GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long
#End If.

What library is missing?

The problem is that you are using conditional compilation incorrectly
As part of VBA7 (A2010) PtrSafe and LongLong / LongPtr were added

PtrSafe
actually does nothing other than tell the compiler the statement is safe to use in VBA7
LongLong is used for pointers BUT only works in 64-bit whereas LongPtr has the same purpose but works in both 32-bit & 64-bit.
You should NOT use a brute force approach and convert all Long to LongLong/LongPtr.
If you do so, the statement will compile but may not work in 64-bit
NOTE: I am guilty of doing exactly this in the past and am currently in the process of converting all such APIs properly.

Taking a different API as an example, the older 32-bit version is
Code:
Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
(ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, _
   ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long

Below is one method of dealing with conditional compilation for this API:

Code:
#If Win64 Then 'PtrSafe and datatype LongLong for pointers
   Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
   (ByVal hwnd As LongLong, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, _
   ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongLong
#ElseIf VBA7 Then ‘32-bit Office with VBA7
     Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
   (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, _
ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
#Else 'older 32-bit Office
    Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
   (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, 
ByVal lpParameters As String, _
   ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
#End If

However, its unnecessarily complex. If we use LongPtr instead of LongLong, the first two sections can be combined

Code:
#If VBA7 Then ‘32-bit or 64-bit Office with VBA7
    Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
   (ByVal hwnd As LongPtr, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, _
   ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongPtr
#Else 'older 32-bit Office
    Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
   (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, _
   ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
#End If

BUT if all of your users are running 2010 or later, you don’t need the else part so this can be reduced to:

Code:
Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
   (ByVal hwnd As LongPtr, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, _
   ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongPtr

Returning to your GetUserName API, it should be written as
Code:
 #If VBA7 Then
   Declare PtrSafe Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" _
   (ByVal lpBuffer As String, nSize As Long) As Long
#Else
   Declare Function apiGetUserName Lib "advapi32.dll" Alias "GetUserNameA" _
   (ByVal lpBuffer As String, nSize As Long) As Long
#End If

Or if all users are running 2010 or later then just use
Code:
Declare PtrSafe Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" _
   (ByVal lpBuffer As String, nSize As Long) As Long

==============================================
Having got that out of my system, the GetUserName API is just one of three methods of getting that information

The other two are much simpler:
a) Environ(“UserName”)
b) CreateObject("WScript.Network").UserName

Neither of these require an API so work as written in both bit-nesses and all versions of Access (from A97 onwards!)
However the Environ function can be ‘spoofed’ so the WScript method is preferred

Hope some of this was of use to you or others!
 
Last edited:

Users who are viewing this thread

Top Bottom