[V8i-SS2 VBA] reading variable from un-opened VBA Projects

Hi Folks,

I am writing a utility to  read utility versions for all my MVBA Projects. Will I need to open all in this code in order to do this?

I have highlighted where I got to so far.

 

' ---------------------------------------------------------------------
'   GetToolVersions
'   Lists all strVERSION values for all MVBA Utilities
'
'   Set a reference to the Microsoft Visual Basic for Applications
'   Extensibility 5.3 library (in Tools | References...)
'   VBIDE is the code name of this library.
' ---------------------------------------------------------------------
Public Sub GetToolVersions()
    '   Check for KeyinArguments
    Dim args()              As String
    Dim nArgs               As Integer
    args = Split(application.KeyinArguments, ",")
    nArgs = 1 + UBound(args) - LBound(args)
    If (1 < nArgs) Then
        Dim UName           As String
        Dim PWord           As String
        UName = args(1)
        PWord = args(2)
    Else
        '   Wrong number of arguments
    End If
   
    '   Prepare code project definitions
    Dim oVBE                As VBIDE.VBE
    Set oVBE = VBE
    Dim oProject            As VBIDE.VBProject
    Dim oProjects           As VBIDE.VBProjects
    Set oProjects = VBE.VBProjects
    Dim vbaAutoloads        As String
    Dim vbaProjects()       As String
    '   VBA requires the following as a variant and not a string
    Dim vbaProject          As Variant
   
    '   Get an array of AutoLoad VBA Project Names
    With ActiveWorkspace
        If .IsConfigurationVariableDefined("MS_VBAAUTOLOADPROJECTS") Then
            vbaAutoloads = .ConfigurationVariableValue("MS_VBAAUTOLOADPROJECTS", True)
        End If
        If .IsConfigurationVariableDefined("MS_VBAREQUIREDPROJECTS") Then
            vbaAutoloads = vbaAutoloads & ";" & .ConfigurationVariableValue("MS_VBAREQUIREDPROJECTS", True)
        End If
    End With
    vbaProjects = Split(vbaAutoloads, ";")
   
    '   Check each VBA project from list of AutoLoad VBA's
    Dim Count               As Long
    For Each vbaProject In vbaProjects
        '   Get MVBA as path and fullname
        Dim strName         As String
        Dim arrNames()      As String
        Dim intIndex        As Integer
        Dim PrjName         As String
        Dim strVersion      As String
        strName = vbaProjects(Count)
        arrNames = Split(strName, "\")
        intIndex = UBound(arrNames)
        PrjName = arrNames(intIndex)
        Debug.Print "File name: " & PrjName
        '   Get Procedure > Module constant strVERSION
        Dim oProj As VBProject
        Set oProj = vbaProject
        strVersion = oProj.EE_Header.strVersion
        Debug.Print "Version: " & strVersion
        Count = 1 + Count
    Next vbaProject
End Sub

  • Unknown said:
    I have highlighted where I got to so far.

    '   Get Procedure > Module constant strVERSION
            Dim oProj As VBProject
            Set oProj = vbaProject
            strVersion = oProj.EE_Header.strVersion
            Debug.Print "Version: " & strVersion

    And what is your issue or question if you got so far?

    Is "strVersion = oProj.EE_Header.strVersion"  giving the value you are looking for?

    Regards

    Frank

    since 1985: GIS, CAD, Engineering (Civil)  Senior Consultant : [Autodesk Civil 3D , Esri ArcGIS, VertiGIS: in previous days : Bentley MS V4 - V8i, GeoGraphics, Bentley Map V8i, InRoads,  HHK Geograf, IBr DAVID] :  Dev: [C, C++, .NET, Java, SQL, FORTRAN, UML]
    [direct quote by: http://en.wikipedia.org/wiki/Helmut_Schmidt]: "Wer Kritik übel nimmt, hat etwas zu verbergen"
    Wer Grammatik- und/oder Rechtschreibfehler findet, der darf sie behalten :-)

  • Hi,

    when I needed something similar, I have used following code. It uses VBA project events OnProjectLoad/OnProjectUnload to add/remove unique configuration variable with name of my project. Then it is easy to list all my loaded VBA tools.

    Option Explicit

    ' Some native declarations
    Declare Function mdlSystem_getCfgVarByIndex Lib "stdmdlbltin.dll" ( _
      ByRef name As LongByRef translation As LongByRef level As Long, _
      ByRef lock_ As LongByVal index As LongAs Long

    Private Declare Function lstrlen Lib "kernel32.dll" Alias "lstrlenA" ( _
      ByVal lpString As LongAs Long

    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" ( _
      Destination As Any, Source As Any, ByVal Length As Long)
      
    Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    Private Declare Function GetTickCount Lib "kernel32" () As Long

    Dim my_project_id As Long

    ' implement this method for each project
    Public Sub OnProjectLoad(Optional dummy As Boolean)
      Sleep 50
      my_project_id = GetTickCount()
      Dim cfg_name As String
      cfg_name = "_VBA_PROJECT_" & my_project_id
      ActiveWorkspace.AddConfigurationVariable cfg_name, "Project Counter"False
    End Sub

    ' implement this method for each project
    Public Sub OnProjectUnload(Optional dummy As Boolean)
      Dim cfg_name As String
      cfg_name = "_VBA_PROJECT_" & my_project_id
      ActiveWorkspace.RemoveConfigurationVariable cfg_name
    End Sub

    ' get VBA string from C string pointer
    Public Function StrFromPtr(ByVal lpStr As LongAs String
     Dim bStr() As Byte
     Dim cChars As Long
     On Error Resume Next
     ' Get the number of characters in the buffer
     cChars = lstrlen(lpStr)
     If cChars Then
      ' Resize the byte array
      ReDim bStr(0 To cChars - 1As Byte
      ' Grab the ANSI buffer
      Call CopyMemory(bStr(0), ByVal lpStr, cChars)
     End If
     ' Now convert to a VB Unicode string
     StrFromPtr = StrConv(bStr, vbUnicode)
    End Function

    Public Sub CountOpenProjects()
      Dim i As Long
      Dim cfg_name As String
      Dim cfg_val As String
      Dim cfg_name_ptr As Long
      Dim cfg_val_ptr As Long
      Dim cfg_level As Long
      Dim cfg_lock As Long
      
      i = 0
      While (0 = mdlSystem_getCfgVarByIndex( _
        cfg_name_ptr, cfg_val_ptr, cfg_level, cfg_lock, i))
        
        cfg_name = StrFromPtr(cfg_name_ptr)
        'Debug.Print cfg_name
        If cfg_name Like "_VBA_PROJECT_*" Then
          cfg_val = StrFromPtr(cfg_val_ptr)
          Debug.Print cfg_val
        End If
        
        i = i + 1
      Wend
      
    End Sub
  • Unknown said:
    I am writing a utility to  read utility versions for all my MVBA Projects. Will I need to open all in this code in order to do this?

    To read a file, whether it's Excel, Word, DGN or VBA, you must first open it.  It looks like you want to read some data in another VBA project, in which case that project must be...

    1. Accessible (i.e. MicroStation can find it using MS_VBASEARCHDIRECTORIES)
    2. Loaded into MicroStation's list of VBA projects

    I guess your question is really "Can I read a variable in another project without starting and running that project?" The answer is 'no'.  One solution might be to provide a GetVersion method in each project, that returns that project's data of interest...

    ' Code in OtherProject
    Public Function GetVersion () As String

      GetVersion = strVersion
    End Function

    Now you can execute that function with this call from your information-harvesting code...

    ' Code in InformationHarvester project
    Dim otherProjectVersion As String

    otherProjectVersion  = [OtherProject]module1.GetVersion

    That statement of course loads the other project, but it's not the other project's main entry point (by convention, Main()) so it does not fire up the entire project.  However, if the other project does some stuff automatically when it's loaded (i.e. an OnProjectLoad event handler) you can't prevent that happening.

     
    Regards, Jon Summers
    LA Solutions

    Answer Verified By: cweber 

  • Thankyou all for the feedback.

    I suspected that I would have to open each project, but was wondering whether there was another way around it.

    I believe that Jon's suggestion will be the simplest to implement. It also overcomes an issue with supplying a password when required.

    I had implemented something similar to what DanPaul offered once when dealing with ProjectWise. I deprecated it in the end as integration with MicroStation is nowhere near as good as it needs to be; I experienced many issues that only delving into PW API would resolve.

  • I ran into a couple of problems

    1. Get value from string of project.module.localvariable name

    http://communities.bentley.com/products/microstation/microstation_programming/f/343173/p/91533/262507.aspx#262507

    2. When calling other projects

    I cannot create cyclic references where some other projects refeerence this one anyway.

     

  • Thank you so much for posting your code! Very helpful for my current task of automating the logging of all my tools (hundreds and hundreds of Subs).