Problem Using the ProjectWise SDK with VBA in Microsoft Access

When I want to connect to PW in Access with aaApi_LoginDlg (0, 0, 0, 0, 0, 0), no Datasource is displayed.

Identical VBA code works perfectly with Excel. it's amazing that this external dll doesn't work the same with Excel and Access.

My IT thinks it's because the SDK doesn't know where the data source server is, but it doesn't have the solution.

  • Didier,

    This function has been deprecated, but it should still work.

    Take a look at MostOfDavesClasses to see how it is used in C#.

    As for not getting a list of datasources, that's something you can check with ProjectWise Explorer.  If the machine you are running your code on isn't configured to query specific sources for datasources, ProjectWise Explore (and the API functions), won't "see" any datasources (unless UDP is enabled and the ProjectWise server machine and client are on the same network).

  • Hello, thank you
    Touching UDP does not change anything.

    So I tried to search the data sources to choose the user, then log it.

    Call :

    Option Explicit
    
    Public Declare Function aaApi_SelectDatasourcesByServer2 Lib "dmscli.dll" ( _
                                                                        ByVal ulFlags As Long, _
                                                                        ByVal strServerAddr As Long, _
                                                                        ByVal ulType As Long) As Long
    
    Public Declare Function aaApi_GetDatasourceName Lib "dmscli.dll" (ByVal lIndex As Long) As Long
    
    Public Declare Function aaApi_Login Lib "dmscli.dll" (ByVal lDsType As Long, _
                                                        ByVal lpctstrDSource As Long, _
                                                        ByVal lpctstrUser As Long, _
                                                        ByVal lpctstrPassword As Long, _
                                                        ByVal lpctstrSchema As Long _
                                                        ) As Long
    
    Global oDocument As clsPWDocument
    
    'Public Const ServeurPW = "projectwise-ss4.egis.fr" error DNS
    Public Const ServeurPW = "10.129.20.5"
    
    Sub Lancement()
    
    Dim Result As Boolean
    
        Set oDataSource = New clsPWDataSource
        Result = oDataSource.LoginDataSource()
        Stop
    
    End Sub

    And in the class module

    Public Function LoginDataSource() As Boolean
    Dim Nombre As Long
    Dim lOk As Long
    Dim strptrNomServeur As Long
    Dim NomServeur As String
    Dim strptrDataSource As Long
    Dim NomDataSource(1000) As String
    Dim NbDataSource As Long
    Dim NumDataSource As Long
    Dim lpctstrDSource As Long
    Dim lIndex As Long
    
        ' Récupère le nom des DataSources
        NomServeur = ServeurPW ' C'est une constante, donc intégrée au code : StrPtr ne peux pas la trouver
        strptrNomServeur = StrPtr(NomServeur)
        LoginDataSource = True
        Nombre = aaApi_SelectDatasourcesByServer2(0, strptrNomServeur, 0)
        Select Case Nombre
        Case Is = 0
            MsgBox "Pas de DataSource trouvée"
            Stop
            LoginDataSource = False
            Exit Function
        Case Is = -1
            lOk = aaApi_ShowLastErrorMessageBox ' renvoie un strptr sur le message de l'erreur
            Stop
            LoginDataSource = False
            Exit Function
        End Select
    
        NbDataSource = Nombre
        For lIndex = 0 To Nombre - 1
            strptrDataSource = aaApi_GetDatasourceName(lIndex)
            NomDataSource(lIndex + 1) = VBStringFromPtrW(strptrDataSource)
        Next lIndex
    
        ' Ecran de choix
        ' resultat NumDataSource
    
        ' Connect
        lpctstrDSource = StrPtr(NomDataSource(NumDataSource))
        lOk = aaApi_Login(0, lpctstrDSource, 0, 0, 0)
        If lOk = 0 Then
            MsgBox "Erreur login"
            Stop
            LoginDataSource = False
        End If
            
    End Function

    aaApi_SelectDatasourcesByServer2  answer "File not found C:\program Files\Bentley\ProjectWise\bin\dmscli.dll"

    I checked, dmscli is present and contains the called function.

    It looks like dmscli is calling another function that is not found.

    But where it is very strange is that the same code works under excel. How is it possible ?

  • Didier,

    I'm not sure why the file wasn't found assuming that the path is correct, but there is a mismatch on the signature of the function compared to how you declared it.

    The actual signature looks like this:

    You declared the function to have a three signed longs as parameters, which doesn't match the documentation, so perhaps Windows doesn't recognize the entry point and can't "find" the function?

    Here's how you would declare it using C#:

    Now, I'm not an expert in "VBA", so perhaps three longs will work, but since the second long is really a pointer to a "string", your code would have to take that into account so that the ProjectWise API function interprets it as a string, and from what I can tell, it looks like you are doing that with a call to StrPtr.

    I can't really help you with VBA to WIN32 issues as VBA isn't something I have any "real" experience with.  The ProjectWise API works from C, C++, and can be made to work with other languages such as C# if you correctly "map" the API function signatures.  Perhaps someone else can help you with using VBA interacting with unmangaged code.  Sorry I can't help you more on this part.

  • Dan,

    VBA is much simpler than C, it does not intrinsically know the subtleties such as unsigned integer, memory pointer, or even what UNICODE is.

    LONG, ULONG, PLONG, LPWSTR and even BOOLEAN, which occupy four bytes in memory are seen by VBA as Long. In VBA, Null represents absolutely nothing, while the NULL of C is a zero on 4 bytes.

    To process UNICODE, you must call Kernel32 functions, being careful to reserve memory for the aaAapi functions which return strptr (UNICODE occupies ANSI * 2 +1 bytes).

    The kernel of my code, almost 2,000 lines, is in four class modules that call almost 80 aaAapi, and in Excel everything works.

    To write my code, I was largely inspired by what is here: using-the-projectwise-api-in-vba, although this code has a lot of bugs and logic errors.

    I think there is a bug in dmscli (I'm pointing to the 64-bit version), which crashes when called from Access. It's incomprehensible.

  • Hi ,

    To get to the bottom of this issue quickly I think 2 checks are in order to confirm first, then 1 very specific need justified after.

    Two checks

    1. Unless COM is used and called from EXE to EXE (or having a system driver), bitness of DLLs is required to match by Microsoft calling and comparability conventions.  Can you verify both Access and ProjectWise DLLs being references are definitely both 64-bit dlls?  An easy way to do this is to open each application and confirm next to the Application Name "(32 bit)" being present or not.  Otherwise use Visual Studio's dumpbin tool like this to confirm each DLL's bitness. e.g. dumpbin /all BMakedll.dll | findstr -c:"word machine" 
    2. Microsoft Office applications can have different VBA permissions.  Can you confirm both Access and Excel are configured accordingly? See: Enable or Disable macros in Office files.

    One need

    If the above cannot help resolve the issue(s), it is recommended to reduce code and data to the minimum and zip provide a "test case" for review/proof (w/o guessing - portable and hopefully reproducible).

    Although not our domain and support expertise, we do provide these Microsoft support topics/articles that may also provide more insights to help resolve the issue(s): Debugging VBA and Troubleshooting.

    HTH,
    Bob