How to access ProjectWise via VB.net or VBA

ProjectWise Programming

This is where you can find and contribute to discussions, ideas, and other information about developing with any ProjectWise SDK.

How to access ProjectWise via VB.net or VBA

  • rated by 0 members
  • This post has 13 Replies |
  • 2 Followers
  • Maik,

    I think I have gotten that error when I forgot to initalize or did not use the right flags for that function.  Other than that, the error usualy means that it can not get to the Projectwise server because of a network issue. 

     Hope that helps.

  • Hi,

    I got my (and some other) VBA examples working, but not in Microstation.
    First of all I needed to get the ProjectWise/bin directory into the Sytem Path variable. Afterwards I was able to manage a log in from MS Office documents into ProjectWise. That worked fine, but with the same source code Microstation threw the error 55025 (invalid socket / connection to remote host broken).

  • Maik,

              I have done the logon from a non-integrated app many, many  times, so I know it is possible.  I am glad that Dave was able to help you with the c / vb interface.

  • Hi,

    Dave, thank you for your wrapper class, we'll check for it as soon as we compiled the dll.

    Inspired by Rons statement I checked my vba from a Microstation DesignFile which is stored in ProjectWise, so I'm already logged in.
    As result I noticed that all of the functions worked (with the StrConv()-converted connection strings) and I was able to connect as another user or even in another datasource and read out the userID for example.

    But our issue is to get access from an external "non-integrated application". So I hope it's possible with the API.

     

  • If you are using an integrated MicroStation session (i.e. the file opened in MicroStation is opened from ProjectWise) then you do not need to login.

     You only need to login when you are using an external "non-integrated application"

     HTH

     Ron

  • I always have a hard time getting the strings to go to VB and come back right so I tend to write wrapper functions that do the string conversion for me. Getting the "Declares" right is also a challenge.  It's a little extra work, but you end up with a reliable solution.  So, for instance, my wrapper functions in the DLL look like this:

    BOOL _mcmMain_GetDocumentIdByFilePath
    (
    LPCSTR szFileNameP,
    long *lProjNoP,
    long *lDocNoP
    )
    {
    LPGUID fileGuidsP = NULL;
    int iNumGuids = 0;
    BOOL bRetVal = FALSE;
    if (SUCCESS == aaApi_GetGuidsFromFileName (&fileGuidsP,
    &iNumGuids, (char *) szFileNameP, TRUE))
    {
    if (1L == aaApi_GUIDSelectDocument ((LPCGUID)&fileGuidsP[0]))
    {
    bRetVal = TRUE;
    if (lProjNoP)
    {
    *lProjNoP = aaApi_GetDocumentNumericProperty (DOC_PROP_PROJECTID, 0);
    }
    if (lDocNoP)
    {
    *lDocNoP = aaApi_GetDocumentNumericProperty (DOC_PROP_ID, 0);
    }
    }
    }
    aaApi_Free ((LPVOID) fileGuidsP);return bRetVal;
    }
    char gszPath[512];extern "C" LPCSTR __stdcall ExpImpRasterChild_GetProjectPathFunctionToBeCalledFromVBA
    (
    LPCSTR szDocumentFileNameP // i - full file name, regular chars from VB
    )
    {
    AFX_MANAGE_STATE( AfxGetStaticModuleState() );
    TCHAR wcFileName[512];memset (wcFileName, 0, sizeof (wcFileName));mbstowcs(wcFileName, szDocumentFileNameP, strlen (szDocumentFileNameP));long lProjNo = 0L, lDocNo = 0L;aaApi_Initialize (AAMODULE_ALL);memset (gszPath, 0, sizeof (gszPath));_mcmMain_GetDocumentIdByFilePath (szDocumentFileNameP, &lProjNo, &lDocNo);if (lProjNo != 0 && lDocNo != 0)
    {
    TCHAR wcPath[512];
    memset (wcPath, 0, sizeof (wcPath));if (aaApi_GetProjectNamePath (lProjNo, TRUE, _T('\\'), wcPath,
    sizeof (wcPath) / sizeof (TCHAR)))
    {
    if (wcslen(wcPath) > 0)
    {
    wcstombs(gszPath, wcPath, wcslen (wcPath));
    }
    }
    }
    return gszPath;
    }

     

    Notice use of LPCSTR vs. LPCTSTR as the the pointer type and the __stdcall decoration of the function signature.  You'd export in a DEF file.  The VBA (this is a MicroStation VBA macro) looks like this:

    Public Declare Function ExpImpRasterChild_GetProjectPathFunctionToBeCalledFromVBA _
    Lib "ExpImpRasterChild.dll" (ByVal sFileName As String) As Long
    'function from operating system for converting strings from C format to VB format
    Public Declare Function lstrcpyn Lib "kernel32" Alias "lstrcpynA" _
    ( _
    ByVal lpString1 As String, _
    ByVal lpString2 As Long, _
    ByVal iMaxLength As Long _
    ) As Long
    'strings coming back from a DLL (C Strings) need this to be turned into VB Strings
    Public Function GetStringFromBuffer(ByVal lRetVal As Long) As String
    Dim sStringVal As String
    Dim lNewSize As Long

    sStringVal = VBA.Space(512)
    lNewSize = Len(sStringVal)

    Call lstrcpyn(sStringVal, lRetVal, lNewSize - 1)

    Dim iFind As Integer

    iFind = InStr(sStringVal, " ")

    If iFind <> 0 Then
    GetStringFromBuffer = VBA.Left(sStringVal, iFind - 2)
    Else
    GetStringFromBuffer = sStringVal
    End If
    End Function
    Public Sub CmdShowPWPath()Dim lResp As Long

    lResp = ExpImpRasterChild_GetProjectPathFunctionToBeCalledFromVBA(ActiveModelReference.DesignFile.FullName)

    Dim sPathName As String

    sPathName = GetStringFromBuffer(lResp)
    MsgBox "PWPath: " & sPathNameEnd Sub

     

    I spent too much time trying to get those Declares right and decided this was the most efficient approach.  Maybe not the best solution for VB only developers, but then again, I'd never recommend doing a lot of PW customization in VB.

    Dave

     

  • Please see example by private email.

    Best Regards,

    Ian Emery.

  • Hej,

    I forgot to transform my strings to LCPWSTR type (whatever) and tryed following example.

    Public Declare Function aaApi_Initialize Lib "DMSCLI.dll" (ByVal ulModule As Long) As LongPublic Declare Function aaApi_Login Lib "DMSCLI.dll" (ByVal lDsType As Long, ByVal lpctstrDSource As String, ByVal lpctstrUser As String, ByVal lpctstrPassword As String, ByVal lpctstrSchema As String) As BooleanPublic Declare Function aaApi_LoginDlg Lib "DMAWIN.dll" (ByVal lDsType As Long, ByVal lptstrDataSource As String, ByVal lDSLength As Long, ByVal lpctstrUsername As String, ByVal lpctstrPassword As String, ByVal lpctstrSchema As String) As Boolean
    Public DataSourceName As String
    Public UserName As String
    Public Password As String
    Sub Login()   init = aaApi_Initialize(AAMODULE_ALL)
       DataSourceName = "ppwsrv:pwmtst"
       UserName = "testuser"
       Password = "pwd"
       If aaApi_Login(AAAPIDB_UNKNOWN, StrConv(DataSourceName, vbUnicode), StrConv(UserName, vbUnicode), StrConv(Password, vbUnicode), StrConv(vnNullString, vbUnicode)) = False Then

          LoginDlg = aaApi_LoginDlg(AAAPIDB_UNKNOWN, StrConv(DataSourceName, vbUnicode), Len(StrConv(DataSourceName, vbUnicode)), StrConv(UserName, vbUnicode), StrConv(Password, vbUnicode), StrConv("", vbUnicode))
       End IfEnd Sub

     

    init returns true, the first LogIn false and the LogInDlg opens the LogIn dialog where my datasourcename and username are filled in but I need to fill in password by myself. Unfortunately the LogIn with dialog failed too. It throws error 55025 -  invalid socket and sometimes error 32768 - logIn error (but can't reproduce it now).
    My string conversion works as the passed datasourcename and username was readable in dialog. I searched for a way to implement the c type strings but found just StrConv() to get the usual vb strings to (I hope) a compareable structure in vbUnicode. There was a BDNzine example in wiki using this technique, but a helper class was missing to use the whole example.
    Without the conversion those values looked like gibberish (灰獷癲琺獥獴档汵敺敥).
    But I didn't find an alternative string type for the declaration of the aaApi functions.

    Maybe one of you knows a better way to implement lcpwstr or help me otherwise.

    Thank you,
    Maik.

     

  • Marek,

    I would also suggest that you get the handle to the logged on datasource with m_hDataSource = aaApi_GetActiveDatasource() so you can log out with aaApi_LogoutByHandle(m_hDataSource);

    By the way, If you do logon with more than one logon, the last logon wins while it is logged in, then once you log out you are still logged in as the previous logon.  Make sure your login(s) match your logout(s). 

  • Dear Maik,

     First use AAAPIDB_UNKNOWN in the login functions

    I would replace the aaApi_LoginAdmin with aaApi_Login to allow alow single sign on - you can login as an administrator with aaApi_Login  there is a differnce between the two but for a normal user side application aaApi_Login should suffice (for normal or admin user) aaApi_LoginAdmin has additional requirements.

    if this call fails the use aaApi_LoginDlg to show the login dialog note the return type is IDOK etc.

    if  ! aaApi_Login then

            if(! aaApi_LoginDlg then

                    really fail..

    else

        success..

    Also make sure your vb strings are in the correct format they may need to be convered from VB strings to c type LPCWSTR and have the correct null terminator. I tryed this some time ago i was not really successful and spent more time converting vb data type to C/C++ data types than any thing else.

    Best Regards,

    Ian Emery

     
  • Hi

    and thanks for your answers. I got the ProjectWise SDK installed and I tried to get access by Microstation VBA. Therefore I wrote the following source code:

    Public Declare Function aaApi_Initialize Lib "DMSCLI.dll" (ByVal ulModule As Long) As Long
    Public Declare Function aaApi_GetCurrentUserId Lib "DMSCLI.dll" () As Long
    Public Declare Function aaApi_AdminLogin Lib "DMSCLI.dll" (ByVal lDsType As Long, lpctstrDSource As String, ByVal lpctstrUser As String, ByVal lpctstrPassword As String) As Boolean
    Public Declare Function aaApi_Login Lib "DMSCLI.dll" (ByVal lDsType As Long, lpctstrDSource As String, ByVal lpctstrUser As String, ByVal lpctstrPassword As String, ByVal lpctstrSchema As String) As Boolean
    Sub LogIn()
       'Initialize the API
       result1=aaApi_Initialize(AAMODULE_ALL)
       'Login to PW as Admin using Userdata
       result2=aaApi_AdminLogin(AAAPIDB_ORACLE, "ppwsrv:pwmtst", "username", "password")
       'Login to PW using single sign-on
       result3=aaApi_Login(AAAPIDB_ORACLE, "ppwsrv:pwmtst", vbNullString, vbNullString, vbNullString)
       result4=aaApi_GetCurrentUserId()
    End Sub


    As results I got true for the Initialize function but false for the two LogIn functions and zero for the UserID (because access wasn't established).

    If I'm logged on to ProjectWise Explorer and run this example out of a Microstation DGN stored in PW without the LogIn functions the aaApi_GetCurrentUsreId function will return the correct ID of the active user. But I need access from desktop without having PW Explorer started.

    The references of the mvba are nothing but the default references.
    Is there anything wrong with my datasource string? I tried nearly everything ^^
    I also tried using AAAPIDB_UNKNOWN instead of AAAPIDB_ORACLE.
    I hope someone may help my and give me some hints to get started with this. I guess the rest would be easier.

    Thanks in advance,

    Maik.

  • Maik,

     Yes you will definately need the SDK. Based on your example of what you are trying to achieve you can do this all directly within the VBA application without the need for COM. You will need the SDK docs (help files) to locate the functions you require, then you can declare them in your VBA/VB/VB.NET code.

     We have done quite a few VBA routine amendments for existing customers to integrate legacy applications into ProjectWise.

     HTH

     Ron

  • Maik,

         Yes you need the SDK in order to access the libraries that tie into Projectwise Explorer.  I would recomend writing a COM object in C++ for your ProjectWise funtionality (init, logon, check out file, check in file, etc.)  You can then call the COM object with MSVBA.  If you want to use VB.Net, you will still need to write a wrapper class for the function calls you want to use.  Somebody posted an example of using VB with the api, but VB is limited what it can do without some interface help.  At least this has been my experience.

  • Hi,

    We are introducing ProjectWise (XM) in our company to manage our operational data. In this process I need to customize some of our self written applications. Those are written in vba (mvba) or VB.net and are used to read and scan files (ascii format) and drop them - dependent on the file content - in a directory on a server.
    Now we want our tools to store the files in ProjectWise.

    For now I searched for some simple examples how to access ProjectWise with Microstation VBA (e.g. ‘Using The ProjectWise API In VBA') or VB.net but none of the posted ones did work well (as I didn't have the SDK?). Does anyone have a good sample to start with and to get used to this topic (as I am new to this)?
    I just need to login to the server, create a document and maybe attach some environmental attributes. Do I need to have the SDK installed for my purpose?

    I'd be grateful for any help and example.

    Best regards,

    Maik.

Page 1 of 1 (14 items)