Questions similar to this appear on the Bentley Discussion Groups. These appeared in the VBA discussion group.

Q Configuration Variables (CfgVars)

A MicroStation configuration variables (CfgVars) are used to customise a workspace. They specify files, folders, and other settings specify to a workspace defined by a CAD administrator. There is more information about configuration variables here, and also in your MicroStation and MicroStation VBA help documentation.

Configuration Variable Evaluation

Use the ConfigurationVariableValue and the ExpandConfigurationValue methods of the Workspace object to get the value of a CfgVar.

ConfigurationVariableValue obtains the value of a single variable; by default, it evaluates its current value. An argument to ConfigurationVariableValue would be something like "MS_TAGOUTPUT".

ExpandConfigurationValue obtains the value of a compound variable, by which we mean a variable that is defined in terms of other variables. An argument to ExpandConfigurationValue would be something like "$(_USTN_USER)$(_USTN_USERNAME).txt".

Simple Variable Evaluation

Let's take an example. The variable MS_DEF specifies the default folder where MicroStation looks for DGN files. It's value will be set to something like V:\Projects\Project1\DGN\models\ (that's just an example: your CAD directory structure is likely to be quite different). Whenever MicroStation comes across MS_DEF in your workspace, it knows how to expand that variable to the folder path in order to find a given DGN file. An argument to ConfigurationVariableValue would be something like "MS_TAGOUTPUT".

In VBA, you can use ActiveWorkspace.ConfigurationVariableValue to emulate MicroStation …

Sub TraceMsDef ()
  Const strMS_DEF      As String = "MS_DEF"
  Dim folder           As String
  folder = ActiveWorkspace.ConfigurationVariableValue (strMS_DEF, True)
  Debug.Print strMS_DEF & "=" & folder
End Sub

Compound Variable Evaluation

Configuration variables are often defined in terms of other variables. For example, you might have something like this in your configuration file …

PROJECT_ROOT = V:/Projects/
PROJECT_NAME = Project1
MS_DEF = $(PROJECT_ROOT)$(PROJECT_NAME)/DGN/Models/

Use ExpandConfigurationValue to convert this compound variable to a value …

Sub TraceMsDef ()
  Const strMS_DEF      As String = "MS_DEF"
  Dim folder           As String
  folder = ActiveWorkspace.ExpandConfigurationValue (strMS_DEF)
  Debug.Print strMS_DEF & "=" & folder
End Sub

Is a Configuration Variable Valid?

A configuration variable may be defined, but is it valid? Suppose a CfgVar points to some folder, but that folder does not exist. Suppose that we have this scenario, where MS_CELL is pointing to …

V:\Projects\Workspace\Standards\cells\

but the actual directory name is this (note that the final s is omitted) …

V:\Projects\Workspace\Standards\cell\

The Configuration Validator helps, by verifying the existence of the folder, folders or file to which a CfgVar points.

Is a Configuration Variable Defined?

Often, you want to determine whether a configuration variable is defined or not. Method IsConfigurationVariableDefined of the Workspace is just what you need …

Sub TestCfgVars ()
  TestCfgVar "MS_DEF"
  TestCfgVar "NOT_DEFINED"
End Sub

Sub TestCfgVar (strVarName As String)
  If (IsConfigurationVariableDefined (strVarName)) Then
    Debug.Print "'" & strVarName & "' is defined"
  Else
    Debug.Print "'" & strVarName & "' is not defined"
  End If
End Sub

Environment Variable Evaluation

Operating system environment variables are typically set when you log on to your computer. If your computer is running Windows you can see environment variable settings in the Advanced tab of My Computer, or by using the SET command from a Windows command prompt.

Suppose you want the Windows USERNAME and COMPUTERNAME environment variables. At a Windows command prompt, you can see those names using the SET command. For example …

C:\>set username
USERNAME=CONNECT

C:\>set computername
COMPUTERNAME=CELERATRIX64

MicroStation evaluates operating system environment variables when it cannot find a MicroStation configuration variable of the same name. You can take advantage of this in VBA …

Sub TraceLogonInfo ()
  Dim computerName        As String
  Dim userName            As String

  Const strCOMPUTERNAME   As String = "COMPUTERNAME"
  Const strUSERNAME       As String = "USERNAME"

  computerName = ActiveWorkspace.ConfigurationVariableValue (strCOMPUTERNAME, True)
  Debug.Print strCOMPUTERNAME & "=" & computerName

  userName = ActiveWorkspace.ConfigurationVariableValue (strUSERNAME, True)
  Debug.Print strUSERNAME & "=" & userName
End Sub

List Configuration Variables

Curiously, there's no way in MicroStation VBA to obtain a list of MicroStation configuration variables. There is an MDL function mdlSystem_getCfgVarByIndex to get a configuration variable from its index, but that's only useful if you know beforehand the index of the variable you want to see. Catch-22!

What's more, that function is hard to use from VBA. It uses C pointers and pointer addresses that VBA can't easily handle. Fortunately for you, Bentley Systems staffer Yongan Fu   came up with a solution.

First, declare the MDL function at the beginning of your VBA project, before any other code …

Declare PtrSafe Function mdlSystem_getCfgVarByIndex Lib "stdmdlbltin.dll" ( _
    ByRef name As Long, _
    ByRef translation As Long, _
    ByRef level As Long, _
    ByRef lock_ As Long, _
    ByVal index As Long) As Long

Here's a VBA function that wraps the MDL. Yongan's vital contribution was to figure out the incantation required to convert an MDL address-of-pointer to a Unicode String …

' ---------------------------------------------------------------------
'   GetCfgVarByIndex
'	arg1	String [out]	Name of variable at index
'	arg2	String [out]	Value of variable at index
'	arg3	Long [ind]		Zero-based index into configuration variable table
'   Returns True if index is valid
' ---------------------------------------------------------------------
Private Function GetCfgVarByIndex( _
    ByRef name As String, _
    ByRef translation As String, _
    ByVal index As Long) As Boolean

    GetCfgVarByIndex = False

    Dim address1                            As Long
    Dim address2                            As Long
    If (0 = mdlSystem_getCfgVarByIndex(address1, address2, 0, 0, index)) Then
        name = GetCExpressionValue("(char*)" & address1)
        translation = GetCExpressionValue("(char*)" & address2)
        Debug.Print name & " = " & translation
        GetCfgVarByIndex = True
    End If
End Function

Here's a VBA function that lists all configuration variables …

Sub TestGetCfgVarNameByIndex()
    Dim index                               As Long
    index = 0
    Dim name                                As String
    Dim value                               As String
    Do While GetCfgVarNameByIndex(name, value, index)
        index = index + 1
        Debug.Print "CfgVar [" & CStr(index) & "] " & name & "=" & value
    Loop
End Sub