Fix incorrect use of 32-bit versions of Windows API functions in SOLIDWORKS macros
Symptoms
System is updated from SOLIDWORKS older than 2012 to a newer version. Or some legacy macro is run. Macro is utilizing Windows API functions (e.g. has browse file/folder dialog, connects to registry, uses windows handles) via Declare Function statement. When started the Compile error: The code in this project must be updated for use on 64-bit systems is displayed.
Cause
SOLIDWORKS has updated the Visual Basic for Application environment in 2013 release from VB6 to VB7. VB6 is 32bit application while VB7 is 64bit application. Due to the difference in variables size in 32/64 it is required to use PtrSafe keyword to assert the environment that it is safe to run the macro in x64 systems and LongPtr or LongLong to properly resolve the Long type variable in 32 and 64 bit environments.
Resolution
- Modify all of the declaration and include PtrSafe keyword and LongPtr as the variable declarations for Long types
- If it is required to support older versions of SOLIDWORKS (prior to 2012) it is possible to use pre-compile conditional statements #IF-#Else
#If VBA7 Then Private Type BROWSEINFO hOwner As LongPtr pidlRoot As Long pszDisplayName As String lpszTitle As String ulFlags As Long lpfnCallback As LongPtr lParam As LongPtr iImage As Long End Type Private Declare PtrSafe Function SHBrowseForFolder Lib "Shell32" (lpbi As BROWSEINFO) As Long Private Declare PtrSafe Function SHGetPathFromIDList Lib "Shell32" (ByVal pidList As LongPtr, ByVal lpBuffer As String) As Long Private Declare PtrSafe Sub CoTaskMemFree Lib "ole32" (ByVal hMem As LongPtr) #Else Private Type BROWSEINFO hOwner As Long pidlRoot As Long pszDisplayName As Long lpszTitle As String ulFlags As Long lpfnCallback As Long lParam As Long iImage As Long End Type Private Declare Function SHBrowseForFolder Lib "Shell32" (lpbi As BROWSEINFO) As Long Private Declare Function SHGetPathFromIDList Lib "Shell32" (ByVal pidList As Long, ByVal lpBuffer As String) As Long Private Declare Sub CoTaskMemFree Lib "ole32" (ByVal hMem As Long) #End If Dim swApp As SldWorks.SldWorks Sub main() Set swApp = Application.SldWorks swApp.SendMsgToUser "Selected folder " & BrowseForFolder End Sub Public Function BrowseForFolder() As String Dim bi As BROWSEINFO Dim pidl As Long Dim path As String bi.lpszTitle = "" bi.ulFlags = 0 pidl = SHBrowseForFolder(bi) If pidl <> 0 Then path = Space$(265) SHGetPathFromIDList pidl, path path = Left$(path, InStr(path, Chr$(0)) - 1) CoTaskMemFree lngPIDL End If BrowseForFolder = path End Function