PTRSafe Question? 32/64 bit office question (1 Viewer)

CHAOSinACT

Registered User.
Local time
Tomorrow, 05:05
Joined
Mar 18, 2009
Messages
235
Well...I think it is a PTRSafe Question anyway... :)

I have a large, complex VBA driven database I develop at work. Its all written by me except a bit of API code I found license free on the net for calling windows open file dialog boxes. Anyway, its suddenly come to my (urgent) attention that its simply not working on all machines.

I've checked the ptrsafe thing months ago and thought it was working fine:

Declare PtrSafe Function ts_apiGetOpenFileName Lib "comdlg32.dll" _
Alias "GetOpenFileNameA" (tsFN As tsFileName) As Boolean

Declare PtrSafe Function ts_apiGetSaveFileName Lib "comdlg32.dll" _
Alias "GetSaveFileNameA" (tsFN As tsFileName) As Boolean

Declare PtrSafe Function CommDlgExtendedError Lib "comdlg32.dll" () As Long

And since it was working on my machine I didn't notice, that on 64bit windows machines running 64 bit office it doesn't work (64bit window with 32 bit office works fine, i had to set up some machines that way for complex MYOB linking reasons). I don't think its the tsGetFileFromUser function, that's served me well forever...any ideas why this won't work on 64 bit machines?


for reference here is the entire module I'm using, including comments of the author for his credit.

'.=========================================================================
'.Browse Files Module
'.Copyright 1999 Tribble Software. All rights reserved.
'.Phone : (616) 455-2055
'.E-mail : carltribble@earthlink.net
'.=========================================================================
' DO NOT DELETE THE COMMENTS ABOVE. All other comments in this module
' may be deleted from production code, but lines above must remain.
'--------------------------------------------------------------------------
'.Description : This module calls directly into comdlg32.dll to allow user
'. to select a filename using the Windows Common Dialog. The
'. user may browse for a file, or enter a file name directly.
'.Written By : Carl Tribble
'.Date Created : 04/05/1999 09:56:31 AM
'.Rev. History :
' Comments : Normally, to use the Common Dialog you need to physically
' place the ActiveX control onto a form and then use code
' behind the form to implement its functionality. This
' module allows you to incorporate the functionality of the
' File Open/Save part of the Common Dialog without the
' ActiveX control itself. This module is completely self-
' contained. Simply copy it into your database to use it.
'.-------------------------------------------------------------------------
'.
' ADDITIONAL NOTES:
'
' This module only provides the Open/Save file dialog, not the other
' CommonDialog interfaces (ColorChooser, Help, PrintDialog, etc.)
'
' If you want your user to browse for folder names (paths) you must use
' the module basBrowseFolders instead.
'
' TO STREAMLINE this module for production programs, you should remove:
' 1) Unnecessary comments
' 2) Flag Constants which you do not intend to use.
' 3) The test procedure tsGetFileFromUserTest
'
'--------------------------------------------------------------------------
'
' INSTRUCTIONS:
'
' ( For a working example, open the Debug window )
' ( and enter tsGetFileFromUserTest. )
'
'.All the arguments for the function are optional. You may call it with no
'.arguments whatsoever and simply assign its return value to a variable of
'.the Variant type. For example:
'.
'. varFileName = tsGetFileFromUser()
'.
'.The function will return:
'. the full path and filename selected or entered by the user, or
'. Null if an error occurs or if the user presses Cancel.
'.
'.Optional arguments may include any of the following:
'. rlngFlags : one or more of the tscFN* constants (declared below)
'. Combine multiple constants like this:
'. tscFNHideReadOnly Or tscFNFileMustExist
'. strInitialDir : the directory to display when dialog opens
'. strFilter : a string containing any filters you want to use. Each
'. part must be separated by the vbNullChar. -example below
'. lngFilterIndex: a 1-based index indicating which filter to start with.
'. strDefaultExt : Extension to use if user does not enter one.
'. strFileName : Default File to display in the File Name text box.
'. strDialogTitle: Caption to display in the dialog's title bar.
'. fOpenFile : Boolean-True for the Open dialog, False for Save dialog.
'
' FILTER EXAMPLE: The filter must be a string containing two parts for each
' filter. The first part is the Description, it is what the user will see
' in the Files of Type box, e.g. "Text Files (*.txt)". The second part is
' the actual filter, e.g. "*.txt". Each part and each filter must be
' separated by the vbNullChar. For example, to provide two filters, one for
' *.mdb files, and one for all files, use a statement like this:
'
' strFilter = "Access (*.mdb)" & vbNullChar & "*.mdb" _
' & vbNullChar & "All Files (*.*)" & vbNullChar & "*.*"
'
' Then pass your strFilter variable as the strFilter argument for the call
' to tsGetFileFromUser()
'
'.--------------------------------------------------------------------------
'.
Option Compare Database
Option Explicit

Declare PtrSafe Function ts_apiGetOpenFileName Lib "comdlg32.dll" _
Alias "GetOpenFileNameA" (tsFN As tsFileName) As Boolean

Declare PtrSafe Function ts_apiGetSaveFileName Lib "comdlg32.dll" _
Alias "GetSaveFileNameA" (tsFN As tsFileName) As Boolean

Declare PtrSafe Function CommDlgExtendedError Lib "comdlg32.dll" () As Long

Private Type tsFileName
lStructSize As Long
hWndOwner As Long
hInstance As Long
strFilter As String
strCustomFilter As String
nMaxCustFilter As Long
nFilterIndex As Long
strFile As String
nMaxFile As Long
strFileTitle As String
nMaxFileTitle As Long
strInitialDir As String
strTitle As String
flags As Long
nFileOffset As Integer
nFileExtension As Integer
strDefExt As String
lCustData As Long
lpfnHook As Long
lpTemplateName As String
End Type

' Flag Constants
Public Const tscFNAllowMultiSelect = &H200
Public Const tscFNCreatePrompt = &H2000
Public Const tscFNExplorer = &H80000
Public Const tscFNExtensionDifferent = &H400
Public Const tscFNFileMustExist = &H1000
Public Const tscFNPathMustExist = &H800
Public Const tscFNNoValidate = &H100
Public Const tscFNHelpButton = &H10
Public Const tscFNHideReadOnly = &H4
Public Const tscFNLongNames = &H200000
Public Const tscFNNoLongNames = &H40000
Public Const tscFNNoChangeDir = &H8
Public Const tscFNReadOnly = &H1
Public Const tscFNOverwritePrompt = &H2
Public Const tscFNShareAware = &H4000
Public Const tscFNNoReadOnlyReturn = &H8000
Public Const tscFNNoDereferenceLinks = &H100000

Public Function tsGetFileFromUser( _
Optional ByRef rlngflags As Long = 0&, _
Optional ByVal strInitialDir As String = "", _
Optional ByVal strFilter As String = "All Files (*.*)" & vbNullChar & "*.*", _
Optional ByVal lngFilterIndex As Long = 1, _
Optional ByVal strDefaultExt As String = "", _
Optional ByVal strFileName As String = "", _
Optional ByVal strDialogTitle As String = "", _
Optional ByVal fOpenFile As Boolean = True) As Variant
On Error GoTo tsGetFileFromUser_Err

Dim tsFN As tsFileName
Dim strFileTitle As String
Dim fResult As Boolean

' Allocate string space for the returned strings.
strFileName = Left(strFileName & String(256, 0), 256)
strFileTitle = String(256, 0)

' Set up the data structure before you call the function
With tsFN
.lStructSize = Len(tsFN)
.hWndOwner = Application.hWndAccessApp
.strFilter = strFilter
.nFilterIndex = lngFilterIndex
.strFile = strFileName
.nMaxFile = Len(strFileName)
.strFileTitle = strFileTitle
.nMaxFileTitle = Len(strFileTitle)
.strTitle = strDialogTitle
.flags = rlngflags
.strDefExt = strDefaultExt
.strInitialDir = strInitialDir
.hInstance = 0
.strCustomFilter = String(255, 0)
.nMaxCustFilter = 255
.lpfnHook = 0
End With

' Call the function in the windows API
If fOpenFile Then
fResult = ts_apiGetOpenFileName(tsFN)
Else
fResult = ts_apiGetSaveFileName(tsFN)
End If

' If the function call was successful, return the FileName chosen
' by the user. Otherwise return null. Note, the CancelError property
' used by the ActiveX Common Dialog control is not needed. If the
' user presses Cancel, this function will return Null.
If fResult Then
rlngflags = tsFN.flags
tsGetFileFromUser = tsTrimNull(tsFN.strFile)
Else
tsGetFileFromUser = Null
End If

tsGetFileFromUser_End:
On Error GoTo 0
Exit Function

tsGetFileFromUser_Err:
Beep
MsgBox Err.Description, , "Error: " & Err.Number _
& " in function basBrowseFiles.tsGetFileFromUser"
Resume tsGetFileFromUser_End

End Function

' Trim Nulls from a string returned by an API call.
Private Function tsTrimNull(ByVal strItem As String) As String
On Error GoTo tsTrimNull_Err
Dim i As Integer

i = InStr(strItem, vbNullChar)
If i > 0 Then
tsTrimNull = Left(strItem, i - 1)
Else
tsTrimNull = strItem
End If

tsTrimNull_End:
On Error GoTo 0
Exit Function

tsTrimNull_Err:
Beep
MsgBox Err.Description, , "Error: " & Err.Number _
& " in function basBrowseFiles.tsTrimNull"
Resume tsTrimNull_End
End Function

'--------------------------------------------------------------------------
' Project : tsDeveloperTools
' Description : An example of how you can call tsGetFileFromUser()
' Calls :
' Accepts :
' Returns :
' Written By : Carl Tribble
' Date Created : 05/04/1999 11:19:41 AM
' Rev. History :
' Comments : This is provided merely as an example to the programmer
' It may be safely deleted from production code.
'--------------------------------------------------------------------------

Public Function tsGetFileFromUserTest() As String
On Error GoTo tsGetFileFromUserTest_Err

Dim strFilter As String
Dim lngFlags As Long
Dim varFileName As Variant


strFilter = "All Files (*.*)" & vbNullChar & "*.*"

lngFlags = tscFNPathMustExist Or tscFNFileMustExist Or tscFNHideReadOnly

varFileName = tsGetFileFromUser( _
fOpenFile:=True, _
strFilter:=strFilter, _
rlngflags:=lngFlags, _
strDialogTitle:="GetFileFromUser Test (Please choose a file)")

If IsNull(varFileName) Then
Debug.Print "User pressed 'Cancel'."
Else
Debug.Print varFileName

End If

If varFileName <> "" Then
MsgBox "You selected the '" & varFileName & "' file.", vbInformation
'Set tsGetFileFromUserTest = varFileName
End If

tsGetFileFromUserTest_End:
On Error GoTo 0
Exit Function

tsGetFileFromUserTest_Err:
Beep
MsgBox Err.Description, , "Error: " & Err.Number _
& " in sub basBrowseFiles.tsGetFileFromUserTest"
Resume tsGetFileFromUserTest_End

End Function
 
Last edited:

RainLover

VIP From a land downunder
Local time
Tomorrow, 05:05
Joined
Jan 5, 2009
Messages
5,041
As you have not pointed out the error if is not possible for me to help except to suggest that you get a later version of the code.

Do a Google search.
 

spikepl

Eledittingent Beliped
Local time
Today, 19:05
Joined
Nov 3, 2010
Messages
6,144
Google indeed. There is quite a number of "it doesn't work"-errors to choose from :D
 

RainLover

VIP From a land downunder
Local time
Tomorrow, 05:05
Joined
Jan 5, 2009
Messages
5,041
Spike

I finally got up off the floor.

This post of yours has just been awarded the post of the day award.
 

CHAOSinACT

Registered User.
Local time
Tomorrow, 05:05
Joined
Mar 18, 2009
Messages
235
Yeah Yeah, I know.

But seriously, it just doesn't.

To elaborate further though:

Declare Function ts_apiGetOpenFileName Lib "comdlg32.dll" _
Alias "GetOpenFileNameA" (tsFN As tsFileName) As Boolean

got changed in 64-bit systems too:

Declare PtrSafe Function ts_apiGetOpenFileName Lib "comdlg32.dll" _
Alias "GetOpenFileNameA" (tsFN As tsFileName) As Boolean

and certain variable declarations modified. I swear they were correct but they seem not to work on 64bit windows running 64bit office. I've found many people with the problem but no solution so far work. At this point easier to move to 32bit office.

edit:

Huh. sometimes your so deep in a problem you don't see Forrest for trees.

I'm working on an access database using a windows api.

In hindsight, maybe not the place to post? lol...

just where I usually head. Sorry if that the case :)
 

spikepl

Eledittingent Beliped
Local time
Today, 19:05
Joined
Nov 3, 2010
Messages
6,144
Ok here is a definition for you:

"It doesn't work" is a general unspecific and completely useless content-free message ( eg. "My VCR doesn't work" !!) just signifying that you are unhappy, but not about what. You always always need to state what happens and how that deviates from your expectation. We cannot guess that and until some sepcifics are provided then all your helpers are flying blind.

What does "it doesn't work" mean here? Do you get an error message? Does the code execute? Or does the system not react to the call at all? Did you debug to see where it stops, if that is what happens? Did you compile the code and that went OK? OR not?
 

CHAOSinACT

Registered User.
Local time
Tomorrow, 05:05
Joined
Mar 18, 2009
Messages
235
Ok here is a definition for you:

"It doesn't work" is a general unspecific and completely useless content-free message ( eg. "My VCR doesn't work" !!) just signifying that you are unhappy, but not about what. You always always need to state what happens and how that deviates from your expectation. We cannot guess that and until some sepcifics are provided then all your helpers are flying blind.

What does "it doesn't work" mean here? Do you get an error message? Does the code execute? Or does the system not react to the call at all? Did you debug to see where it stops, if that is what happens? Did you compile the code and that went OK? OR not?

Actually....nothing happens. Joking!!!

Its a common public routine for calling the windows open file dialog and retrieving a path/file name as string....it should just open the dialog and return the string, and is returning null on machines with 64-bit office (all windows version are 64bit but not all office).

I believe now that there is no comdlg32.dll for 64-bit office, or I have the opening declarations wrong somehow, but I'm not an api programmer, I'm using a public routine as I said. It compiles fine on my machine, I'll try that on the problem machine tomorrow, good idea. I apologize for the original post...I've been head down on this for a while, in my own world...
 

RainLover

VIP From a land downunder
Local time
Tomorrow, 05:05
Joined
Jan 5, 2009
Messages
5,041
You may or may not be aware of this but the good ole Message Box can help in these situations.

It can show you that a certain line of code was executed and can also display a value.

Then there is the step through method. Go to debug for help on this.

You may also use the debug.print method.

These will at least will point you to where the problem lies.
 
Last edited:

CHAOSinACT

Registered User.
Local time
Tomorrow, 05:05
Joined
Mar 18, 2009
Messages
235
You may or may not be aware of this but the good ole Message Box can help in these situations.

It can show you that a certain line of code was executed and can also display a value.

Then there is the step through method. Go to debug for help on this.

You may also use the debug.print method.

These will at least will point you to where the problem lies.

Fist, thanks for responding.

Yeah I know. I just know nothing about the API so it's feedback may be useless with out a lot of research, and I have tight time restraints. Its seems to be a common problem and 90% of posts I see say un-resolvable actually - I just find it hard to believe.

Also, I find a lot of data on my specific problem on the msdn site but they seem never refer to the dll ["comdlg32.dll"] I'm using (and they refer to specif data structure fixes). I've inferred what I can....honestly, at this point I'm switching critical machines back to 32bit office (I should have just done that in the first place, would have saved time), what many recommend, anyway.
 

NigelShaw

Registered User.
Local time
Today, 18:05
Joined
Jan 11, 2008
Messages
1,573
Hi

I haven't checked anything nor have I googled a single thing but I glanced at this and wondered if there was something staring in the face of the confused.

If comdlg32.dll works on the 32 bit machines and not on the 64 bit, is it because comdlg32 is exactly what it is? 32?

Maybe there is a 64 bit equivalent.......

Just a thought :)


Nidge
 

CHAOSinACT

Registered User.
Local time
Tomorrow, 05:05
Joined
Mar 18, 2009
Messages
235
Hi

I haven't checked anything nor have I googled a single thing but I glanced at this and wondered if there was something staring in the face of the confused.

If comdlg32.dll works on the 32 bit machines and not on the 64 bit, is it because comdlg32 is exactly what it is? 32?

Maybe there is a 64 bit equivalent.......

Just a thought :)


Nidge


yeah looked, can't find any reference to a 64bit equivalent....

Thanks for trying though. I'm desperate for some out of the box solution, so anything is welcome.
 

CHAOSinACT

Registered User.
Local time
Tomorrow, 05:05
Joined
Mar 18, 2009
Messages
235
Maybe this might help

http://gpgonaccess.blogspot.co.uk/2010/03/work-in-progress-and-64-bit-vba.html?m=1

From a few of the AWF natives.



Cheers

Nidge

thanks again.
Tragically processed and applied.

The critical difference between this individual and my problem lies in his statement here:

"This stuff matters to anyone moving their Access apps from a 32 bit OS to a 64 bit OS. We're not talking about Access itself here. The default installation for Access 2010 will be the 32 bit version and all of my testing here is in the 32 bit version of Access on a 64 bit OS."

I'm 64/64 not 32/64
 

Kowalski

Registered User.
Local time
Today, 20:05
Joined
Jul 5, 2007
Messages
121
I have the same problem.
Have you found any solutions yet?
 

Solo712

Registered User.
Local time
Today, 14:05
Joined
Oct 19, 2012
Messages
828
What worked for me (credit to http://stackoverflow.com/questions/5724396/excel-64-bit-and-comdlg32-dll-custom-colours):

Change all your Long Data types to LongPtr. That's in both the Function declarations and the Structs and the return types.

Not so fast, Stanley ! :) You don't know that all the Longs in the struc are in fact pointers. That in your routine the assumption worked is no guarantee that it will work in this one. You might get lucky and the nMaxFileTitle or nFilterIndex (which do not look like pointers) will take the 64-bit variable without fussing, but then again they might not and bring the house down ! (Check this article out !). I suspect that Microsoft now distinguishes btw LongLong and LongPtr 4-byte data types (the type checking is unclear) to make developpers aware that not all Long integers in the 32-bit systems are automatically extended to the 64-bit equivalent.

Best,
Jiri
 

Kowalski

Registered User.
Local time
Today, 20:05
Joined
Jul 5, 2007
Messages
121
You can't really tell your clients who are governed by a shared services company what they should install. We will just have to work around it.
 

CHAOSinACT

Registered User.
Local time
Tomorrow, 05:05
Joined
Mar 18, 2009
Messages
235
You can't really tell your clients who are governed by a shared services company what they should install. We will just have to work around it.

True enough.

I'm VERY lucky to be administrator and in a position to easily make that choice.

Having said that, is wasn't just Access or me, MYOB wouldn't support 64 bit properly either. It caused so many problems in the long run there are very good arguments for everyone removing it. I would at least suggest it to them... Surprisingly there are major companies have no intention of ever making their products compatible with 64 bit office - so if the client goes that way they need to understand it will cost them in more than one place.

But of course your right you can't make them do anything.
 

Solo712

Registered User.
Local time
Today, 14:05
Joined
Oct 19, 2012
Messages
828
True enough.

I'm VERY lucky to be administrator and in a position to easily make that choice.

Having said that, is wasn't just Access or me, MYOB wouldn't support 64 bit properly either. It caused so many problems in the long run there are very good arguments for everyone removing it. I would at least suggest it to them... Surprisingly there are major companies have no intention of ever making their products compatible with 64 bit office - so if the client goes that way they need to understand it will cost them in more than one place.

But of course your right you can't make them do anything.

This sounds very familiar to me. When Microsoft introduced Win95/NT most admins wanted to stay away from the new 32-bit apps and chanted homilies to the old 16-bit versions (which were often UAE-infested crap). That included the 4.x versions of the Office (For a while it looked like the 16-bit WPO was going to make a comeback). Any little glitch in the news of a 32-bit issue was deemed a doomsday portent. As soon as the tests were run for the legacy software under the new 32-bit platform and they turned positive, the word was out that the 32-bit versions were dangerous and "evil" and convoluted arguments were offered why they should not be touched. In truth, both the 32-bit Office in 1995 and 64-bit Office in 2010 were ahead of their time, and not quite ready for prime time, mostly because of issues of backward compatibility. But the resistance to the new technology is not explained by that. It's human nature to resist change, especially if systems seem to be working relatively well and the occasional kinks are well understood and under control. The admins feel the new techology was developped to mess up their neat, safe little sandboxes.

From what I hear from my friends, the real problems with the 64-bit Office have mostly to do with hardware. Drivers are either not available or don't work reliably. The third-party Wintel hangons do not particularly feel motivated to support the new office when 99% of their business is in the support of the 32-bit platform. Also, the relatively slow spread of the new technologies is partly Micosoft's own doing because of its insistence that everything must be backward compatible to the times when Bill Gates was crashing in the office and taking shower once a week. Sometimes that policy leads to near-disasters (like Vista). But mostly it maintains the climate of too little incentive to move up. The old stuff still works. Hell, even on this Board a lot of people still stick to Access 2003. It works - the new versions are just hyped-up, overblown, cranky, futile attempts to improve on the perfect small database.

Best,
Jiri
 

Users who are viewing this thread

Top Bottom