Environment Variables for .NET Customization

There are 4 environment variables, with significant values, available for use with the .NET Customization capability.
AVEVA_DESIGN_EXE
should be set to the product installation directory.
CAF_ADDINS_PATH
indicates the location of the AddIns.
CAF_UIC_PATH
indicates the location of files where the GUI is defined.
AVEVA_CAF_TRACING
can be set to obtain information while developing.
AVEVA_DESIGN_EXE
should be set to the product installation directory.
CAF_ADDINS_PATH
indicates the location of the AddIns.
CAF_UIC_PATH
indicates the location of files where the GUI is defined.
AVEVA_CAF_TRACING
can be set to obtain information while developing.
If this environment variable is unset, the program behaves as if it has been set to the product installation directory. The value can be multiple paths, separated by ';' and the application will search all of them in sequence for AddIns.
The application will search for <module_name>Addins.xml in the directories until it finds a matching file. Once a <module_name>Addins.xml file is found, the application searches the directories for files with the same name. The list of addins is read from these xml files, duplicate entries within the matching files are disregarded.
When customizing, users will probably want to have the product installation directory in the path list to locate standard AVEVA AddIns delivered with the product.
The CAF_UIC_PATH implicitly appends the installation folder.
If this environment variable is unset, the program behaves as if it has been set to the product installation directory. The value can be multiple paths, separated by ';' .
The application will search for <module_name>Customisation.xml in the directories until it finds a matching file. Once a <module_name>Customization.xml file is found, the application searches the directories for files with the same name. The list of customization files is read from these xml files, duplicate entries within the matching files are disregarded.
Each <…>Customization.xml file contains a list of .uic files. The path for which may be a filename, when the uic file is in the same directory, or a full pathname to the where the uic file exists.
Files can use the notation '$1.uic'. The application will substitute the current Project Code (E.G. APS) for $1 on start up. An error will be raised if the file is not found unless the Optional="true" has been specified.
For example:
On start-up, the application will look for the uic files specified. An error will be raised if one is not found unless the optional=’true’ has been specified.
The uic files are processed in order. UI containers must have been defined before UI components are added to them.
In addition to using the CAF_UIC_PATH to look for <…>Customization.xml files, the application will also use it to locate resource files.
  <UICustomizationFiles>
    <CustomizationFile Name="Module" Path="admin.uic" />
    <CustomizationFile Name="Project" Path="$1.uic" Optional="true"/>
    <CustomizationFile Name="MessageAddin" Path="MessageAddinMenu.uic" />
  </UICustomizationFiles>
</UICustomizationSet>


The content of a User Interface Customization (UIC) file is created using the CAF based applications’ built-in interactive user interface customization tool available from the Customize window. Click to display the Customize window.

The customization system supports the concept of multiple configuration files. Any number of levels of customization file can be defined either using the module customization configuration file or the CommandBarManager. AddUICustomizationFile() method, and they are layered on-top of each other in the order they appear in the list.

Selecting an entry in the list will update the customize explorer will show command tools with all configuration information defined in the selected file and those above it. Any items in the customize explorer or list of command tools view which are not defined in the currently active customization file are displayed with an italic font in grey.
Any customization file which a user does not have write access to does not appear in the drop-down list, but its contents are included in the customize explorer and list of command tools view.
The selected customization file will become the active customization file. It will only be possible to edit customization information defined in this file.
The Customize Explorer is populated with a representation of the active customization. It shows CommandBars and their contents, Menubars and their entries, Context Menus and their entries and Ribbons and their contents defined in all of the configuration files above and including the currently selected file. It also contains a list of the currently loaded resource files.
When a node in the customize explorer is selected, the property grid is updated with the corresponding object so that its properties can be edited. Only objects which are defined in the currently Active Customization File can have their properties modified.
Selecting a node in the customize explorer which represents an object defined in a non-active file will update the property grid, but it will be disabled, preventing modification.
If the selected node represents a resource file, the Resource Editor will be displayed instead of the property grid.
The tools owned by a MenuTool or Ribbon can be re-ordered by dragging the tool to the new desired position.
The list of command tools is populated with each of the tools defined in each of the configuration files above and including the currently selected file.
Use the functionality available to:
The property grid is updated with the corresponding tool object so that its properties can be edited. Only objects which are defined in the currently active customization file can have their properties modified. Selecting a tool which is defined in a non-active file updates the property grid, but it will be disabled thus preventing modification.
Tools can be dragged from the list of command tools and dropped into a MenuTool or Ribbon in the customization explorer. It is also possible to add tools to a menu or ribbon defined in a higher level customization file.
The functionality can be used to integrate new tools into an existing system defined menu hierarchy and extend system toolbars as well as creating new top level menus and new tabs.
One possible risk of adding tools to menus or ribbons defined at a higher level is that the higher level structure might at a later date be modified making these tools ‘orphaned’, or making the data which is stored to indicate their position within the host invalid. To warn of this, these tools are displayed in red within the customization explorer.
Use the right-click menu available from the List of Command Tools pane of the Customize window to delete, create a tool or get an image from the clipboard.

Delete
Deletes the currently selected tool, if the selected tool is not editable then the delete operation is disabled. If the tool has been used then a warning message is displayed to confirm that the delete should be carried out.

New
Uses the displayed menu to create a new menu tool, create a new tool of the required type with a unique default name (Tool<N>) and add it to the list. New tools can also be created using the icons on the left side of the command tool pane.

The properties for the new menu tool are displayed in the properties grid and can be edited.

Use the functionality available from the property grid to edit the various properties of the tools. The customize explorer or the list of tools is kept up to date with any property changes.

The following properties can be set for all Tools:
The following properties are available on some Command Tools:
If required, the command property can be modified, click . . . in the Command field to display the Command window. By default the command type is set to Command, other command types available for selection are Macro and Command Class, refer to Macro and Command Class for further information.

Here a list of the currently loaded CAF Command objects is displayed for selection.
The macro functionality uses a special command class to invoke the entered single PML command. This enables the PML developer to use the interactive customization tool to create their own menus and commandbars without needing to write C# command classes.

Use the functionality available from the Command window, to select a command class from populated list:

The ribbon section of the explorer enables the creation of tools; application menus, contextual tab groups and tabs, the creation, modification, deletion or group order is identical to that previously described. Refer to Edit an UIC File for further information.

Use of the resource editor enables each of the currently loaded resource sets to be edited. It supports String, Icon and Bitmap resources. Each resource set can comprise a number of resource files, with an Invariant Language resource file and any number of locale specific resource files. When a resource file is selected, the Resource Editor is activated.

When active, the resource editor command bar contains the following operations:

Save
Saves the resource file to the default location.
Copy Resources
Copies a resource file to the clipboard.
Paste Resources
Pastes a resource file into another resource file.
Delete
Deletes a resource file.
Add New Resource File
Adds a new resource file. The resource file name must be typed in the text box adjacent to the icon.

Save
Saves the resource file to the default location.

Copy Resources
Copies a resource file to the clipboard.

Paste Resources
Pastes a resource file into another resource file.

Delete
Deletes a resource file.

Add New Resource File
Adds a new resource file. The resource file name must be typed in the text box adjacent to the icon.
New resource files (icon or bitmaps) can be added using drag-and-drop from a windows explorer. The resource id is generated from the filename, capitalized and prefixed with "ID_". If there is a clash with an existing resource, a confirmation window is displayed prompting for confirmation of file replacement.
Use the property grid to add new string resource(s), double click in the available blank entry in the grid. Once created a new blank row is automatically added to the grid.

Use the Edit Formatted Text window to edit existing resource(s), right click the required string resource in the property grid, from the displayed menu select Formatted Text Editor.

Use the localisable resources functionality to customize a locale specific resource file or add a new locale specific resource file to the resource file set (this can then be selected for editing). Refer to Resource Manager for further information.

Use the standard functionality available for selection from the View Style menu to change how information is displayed in the resource file editor.

The icon and bitmap tabs also have a popup menu which provides access to these functions as well as a rename function. Double clicking on a resource also enters the rename mode.

Properties of tools which are strings or the icon property can use resources for their value. Reference to a resource is made using the form <ResourceSet Name>:<Resource Id> as shown below:

The caption and icon properties can be set on a tool in the tool list by drag-and-drop from the resource editor onto the tool.
There is a standalone version of the resource editor available to enable resource files to be created and edited. This program is called "ResourceEditor.exe" and can be found in the installation directory.
When started it displays a file selection window which enables the choice of an existing resource file or the addition a new resource file.
Select a Node in the List
Drag & Drop from the List to the Customization Explorer
List Context Menu.
Select a Node in the List
Select a Node in the List
Drag & Drop from the List to the Customization Explorer
Drag & Drop from the List to the Customization Explorer
List Context Menu.
List Context Menu.
ApplicationContext
Currently unused
Arguments
List of arguments supplied to the Command
Caption
Text to display on CommandBar
Command
Command to run (see below)
DisplayStyle
Determines how the tool is displayed on the CommandBar
Default- The tool is displayed in a default style.
DefaultForToolType - The tool is displayed based on the default for the tools type and its location.
TextOnlyAlways - The tool is always displayed as text only.
TextOnlyInMenus - The Tool is displayed as a graphic when located on a Toolbar, and displayed as text when located on a Menu.
ImageAndText - The tool is displayed using its assigned image and text. This setting is ignored when the item is on a top-level menu.
ImageOnlyOnToolbars - The Tool is displayed as a graphic when located on a Toolbar, and displayed as image and text when located on a Menu.
Icon
Icon to display on CommandBar
KeyTip
Tip is shown on the ribbon when the Alt key is pressed, aids quick navigation
Name
Unique name for this tool
Shortcut
Shortcut key to activate this tool
Tooltip
Plain tool-tip text to display on mouse-over
TooltipFormattedText
Formatted tool-tip text to display on mouse-over
TooltipTitle
Title for tool-tip
ApplicationContext
Currently unused
ApplicationContext
Arguments
List of arguments supplied to the Command
Arguments
Caption
Text to display on CommandBar
Caption
Command
Command to run (see below)
Command
DisplayStyle
Determines how the tool is displayed on the CommandBar
Default- The tool is displayed in a default style.
DefaultForToolType - The tool is displayed based on the default for the tools type and its location.
TextOnlyAlways - The tool is always displayed as text only.
TextOnlyInMenus - The Tool is displayed as a graphic when located on a Toolbar, and displayed as text when located on a Menu.
ImageAndText - The tool is displayed using its assigned image and text. This setting is ignored when the item is on a top-level menu.
ImageOnlyOnToolbars - The Tool is displayed as a graphic when located on a Toolbar, and displayed as image and text when located on a Menu.
DisplayStyle
Icon
Icon to display on CommandBar
Icon
KeyTip
Tip is shown on the ribbon when the Alt key is pressed, aids quick navigation
KeyTip
Name
Unique name for this tool
Name
Shortcut
Shortcut key to activate this tool
Shortcut
Tooltip
Plain tool-tip text to display on mouse-over
Tooltip
TooltipFormattedText
Formatted tool-tip text to display on mouse-over
TooltipFormattedText
TooltipTitle
Title for tool-tip
TooltipTitle
AutoComplete
Sets whether the edit portion is automatically updated to match an item in the list as new characters are typed.
Control
Control embedded in container
Editable
Sets if the text is editable by the user
MaxLength
Maximum number of characters the user is allowed to enter
Password
Display text in password mode (hidden)
ValueList
List of values to display
Width
Tool width on the CommandBar
AutoComplete
Sets whether the edit portion is automatically updated to match an item in the list as new characters are typed.
AutoComplete
Control
Control embedded in container
Control
Editable
Sets if the text is editable by the user
Editable
MaxLength
Maximum number of characters the user is allowed to enter
MaxLength
Password
Display text in password mode (hidden)
Password
ValueList
List of values to display
ValueList
Width
Tool width on the CommandBar
Width
DockedWindowStateCommand
ModuleSwitchCommand
SelectTaskPaneCommand
CommandBarStateCommand.
DockedWindowStateCommand
DockedWindowStateCommand
ModuleSwitchCommand
ModuleSwitchCommand
SelectTaskPaneCommand
SelectTaskPaneCommand
CommandBarStateCommand.
CommandBarStateCommand.
Note:
Only ribbons and their contents (tabs, groups and menus) are described.
Note:
Functionality is available for icons and bitmaps only.
Note:
The functionality available from the formatted text editor is standard.

Edit an UIC File
Resource Manager
Customize
Customize
CommandBarManager. AddUICustomizationFile()
Customize Explorer
Active Customization File
Resource Editor
Note
:
List of Command Tools
Customize
Delete
New
. . .
Command
Command
Command
Macro
Command Class
Command
Edit an UIC File
Invariant Language
Resource Editor
Save
Copy Resources
Paste Resources
Delete
Add New Resource File
Note
:
Edit Formatted Text
Formatted Text Editor
Note
:
Resource Manager
View Style
resource file editor


The database related interfaces are provided by the interface assemblies:
This interface has the following main classes:
Namespace: Aveva.Core.Database
The class is valid for system types and User Defined Element Types (UDETs).
As well as the class methods there is a lot of functionality that can be accessed via pseudo attributes. The relevant pseudo attributes are listed where relevant.
The classes fall into the following groups:
Aveva.Core.Database.dll & Aveva.Core.Database.Filters.dll
Aveva.Core.Database.dll & Aveva.Core.Database.Filters.dll
Aveva.Core.Database.dll & Aveva.Core.Database.Filters.dll
DatabaseService:
The sole purpose of this class is to open a project.
DbAttribute:
The class has two purposes:
Instances of the class are used to identify and pass around attributes
The methods allow the retrieval of metadata about an attribute, for example: type, size, Name, pseudo or not, etc. The class is valid for system attributes and User Defined Attributes (UDAs).
DB:
This class provides information on the opened Data Bases (DBs).
DbElement:
Instances of DbElement are used to identify an element. This is the main class for reading and writing to the database. The methods cover
element creation
element deletion
copy
getting/setting attributes and rules
navigating the DB
evaluating database expressions.
DbElementType:
The class has two purposes:
Instances of the class are used to identify and pass around Element types
The methods allow the retrieval of metadata about an Element type, for example: Name, description, allowed attributes and members etc.
DatabaseService:
The sole purpose of this class is to open a project.
DatabaseService:
The sole purpose of this class is to open a project.
DbAttribute:
The class has two purposes:
Instances of the class are used to identify and pass around attributes
The methods allow the retrieval of metadata about an attribute, for example: type, size, Name, pseudo or not, etc. The class is valid for system attributes and User Defined Attributes (UDAs).
DbAttribute:
The class has two purposes:
DB:
This class provides information on the opened Data Bases (DBs).
DB:
This class provides information on the opened Data Bases (DBs).
DbElement:
Instances of DbElement are used to identify an element. This is the main class for reading and writing to the database. The methods cover
element creation
element deletion
copy
getting/setting attributes and rules
navigating the DB
evaluating database expressions.
DbElement:
Instances of DbElement are used to identify an element. This is the main class for reading and writing to the database. The methods cover
DbElementType:
The class has two purposes:
Instances of the class are used to identify and pass around Element types
The methods allow the retrieval of metadata about an Element type, for example: Name, description, allowed attributes and members etc.
DbElementType:
The class has two purposes:
DbEvents:
This class contains the mechanisms for subscribing to database events. It covers savework, getwork, undo, redo, flush, refresh, drop events plus capturing general database changes.
DbExpression:
Class to hold a database expression. These are the same as Programmable Macro Language (PML) 1 expressions. Methods to evaluate expressions are on the DbElement class.
DbPseudoAttribute:
This Class allows pseudo attribute code to be plugged in for UDAs.
DbRule:
Class to hold a database rule
DbUserChanges: This is passed through by the 'database change' event. It contains a list of database changes made since the last 'database change' event was raised. Changes may be queried down to the attribute level.
MDB:
Methods to do operations on an Multiple DataBase (MDB), for example: savework, getwork.
Table:
Various classes to access the internal Dabacon tables, for example: the name table.
Project:
The main method is to open the MDB.
DbEvents:
This class contains the mechanisms for subscribing to database events. It covers savework, getwork, undo, redo, flush, refresh, drop events plus capturing general database changes.
DbEvents:
This class contains the mechanisms for subscribing to database events. It covers savework, getwork, undo, redo, flush, refresh, drop events plus capturing general database changes.
DbExpression:
Class to hold a database expression. These are the same as Programmable Macro Language (PML) 1 expressions. Methods to evaluate expressions are on the DbElement class.
DbExpression:
Class to hold a database expression. These are the same as Programmable Macro Language (PML) 1 expressions. Methods to evaluate expressions are on the DbElement class.
DbPseudoAttribute:
This Class allows pseudo attribute code to be plugged in for UDAs.
DbPseudoAttribute:
This Class allows pseudo attribute code to be plugged in for UDAs.
DbRule:
Class to hold a database rule
DbRule:
Class to hold a database rule
DbUserChanges: This is passed through by the 'database change' event. It contains a list of database changes made since the last 'database change' event was raised. Changes may be queried down to the attribute level.
DbUserChanges: This is passed through by the 'database change' event. It contains a list of database changes made since the last 'database change' event was raised. Changes may be queried down to the attribute level.
MDB:
Methods to do operations on an Multiple DataBase (MDB), for example: savework, getwork.
MDB:
Methods to do operations on an Multiple DataBase (MDB), for example: savework, getwork.
Table:
Various classes to access the internal Dabacon tables, for example: the name table.
Table:
Various classes to access the internal Dabacon tables, for example: the name table.
Project:
The main method is to open the MDB.
Project:
The main method is to open the MDB.
Data Model Definition Classes
Basic database access, query and modification.
Filters
Iterators
Dabacon Tables
DBs, MDBs and Projects
Events and pseudo attribute plugins
Data Model Definition Classes
Data Model Definition Classes
Basic database access, query and modification.
Basic database access, query and modification.
Filters
Filters
Iterators
Iterators
Dabacon Tables
Dabacon Tables
DBs, MDBs and Projects
DBs, MDBs and Projects
Events and pseudo attribute plugins
Events and pseudo attribute plugins

Data Model Definition Classes
Filters
Iterators
Dabacon Tables
DatabaseService
DbAttribute
DB
DbElement
DbElementType
DbEvents
DbExpression
DbPseudoAttribute
DbRule
DbUserChanges
MDB
Table
Project
Data Model Definition Classes
Filters
Iterators
Dabacon Tables
DBs, MDBs and Projects


Four classes are available.


There is a single class for all element types.
The purpose of the class is to:
External to the AVEVA module, the hash value can be used to uniquely identify an Element type. The hash value is a 32 bit integer.
In C# a DbElementType object may be obtained in one of three ways:
The methods allow the Element type metadata to be accessed. For example:
Pseudo attributes that provide similar information on a particular element instance (for example, on a DbElement) are:
HLIS
DbElementType[]
List of all possible types in owning hierarchy
LIST
DbElementType[]
List of all possible member types
LLIS
DbElementType[]
List of all possible types in member hierarchy
OLIS
DbElementType[]
List of all possible owner types
REPTXT
String
Reporter text used for element type
ATTLIST
DbAttribute[]
List of all visible attributes for element
PSATTS
DbAttribute[]
List of pseudo attributes
UDALIS
DbAttribute[]
List of UDAs

DbNounManual- Manual category
DbType - DB type
Instances of the class identify the element type. i.e. methods on other classes take a DbElementType as an argument rather than a string to denote an Element type. The DbElementType has 'value' semantics for comparison purposes. i.e. comparing of two DbElementTypes will always return true if they refer to the same type, even if they are different objects.
Access the metadata associated with element types.
Instances of the class identify the element type. i.e. methods on other classes take a DbElementType as an argument rather than a string to denote an Element type. The DbElementType has 'value' semantics for comparison purposes. i.e. comparing of two DbElementTypes will always return true if they refer to the same type, even if they are different objects.
Instances of the class identify the element type. i.e. methods on other classes take a DbElementType as an argument rather than a string to denote an Element type. The DbElementType has 'value' semantics for comparison purposes. i.e. comparing of two DbElementTypes will always return true if they refer to the same type, even if they are different objects.
Access the metadata associated with element types.
Access the metadata associated with element types.
Name
Description
BaseType (for User Defined Element Type [UDETs])
List of attributes
List of User Defined Attributes (UDAs)
Allowed members
Allowed owners
Types that may appear above this element type
Types that may appear below this element type
Element types that may be referenced from a given attribute on this element type
Database types in which it occurs
Name
Name
Description
Description
BaseType (for User Defined Element Type [UDETs])
BaseType (for User Defined Element Type [UDETs])
List of attributes
List of attributes
List of User Defined Attributes (UDAs)
List of User Defined Attributes (UDAs)
Allowed members
Allowed members
Allowed owners
Allowed owners
Types that may appear above this element type
Types that may appear above this element type
Types that may appear below this element type
Types that may appear below this element type
Element types that may be referenced from a given attribute on this element type
Element types that may be referenced from a given attribute on this element type
Database types in which it occurs
Database types in which it occurs

DbElementType[]
DbElementType[]
DbElementType[]
DbElementType[]
String
DbAttribute[]
DbAttribute[]
DbAttribute[]


This is very similar to DbElementType. There is a single class for all attributes.
The purpose of the class is to:
The class should not be confused with the attribute value. The actual Attribute value for a particular Element can only be accessed via the DbElement class. Comparing two DbAttributes just compares whether they identify the same attribute, the comparison does not look at attribute values in any way.
External to the AVEVA module, the hash value can be used to uniquely identify an Attribute. The hash value is a 32 bit integer.
In C# a DbAttribute object may be obtained in the following ways:
The methods allow the following metadata to be accessed:
Attribute Type
Units
Name
Description
Category
Size
Allowed Values
Allowed ranges
Is a UDA
Is a pseudo attribute
Whether the attribute may take a qualifier
Attribute Type
Units
Name
Description
Category
Size
Allowed Values
Allowed ranges
Is a UDA
Is a pseudo attribute
Whether the attribute may take a qualifier
Find the type of attribute XLEN. We use the global instance of XLEN on the DbAttributeInstance class.
DbAttributeUnit -
Type of units, for example: distance or bore or none.
DbAttributeType –
Type of attribute. One of
INTEGER = 1,
DOUBLE = 2,
BOOL = 3,
STRING = 4,
ELEMENT = 5,
DIRECTION = 7,
POSITION = 8,
ORIENTATION = 9
DbAttributeQualifier – used to determine what sort of qualifier an attribute has
DbAttributeUnit -
Type of units, for example: distance or bore or none.
DbAttributeType –
Type of attribute. One of

INTEGER = 1,

DOUBLE = 2,

BOOL = 3,

STRING = 4,

ELEMENT = 5,

DIRECTION = 7,

POSITION = 8,

ORIENTATION = 9
DbAttributeQualifier – used to determine what sort of qualifier an attribute has

using ATT=Aveva.Core.Database.DbAttributeInstance;

DbAttributeType  xlenTyp= ATT.XLEN.Type;
Access the metadata (i.e. data about data) associated with attributes, for example: type, name, length.
Identify attributes. i.e. methods on other classes should always take a DbAttribute rather than a string as an argument to denote the attribute. Any comparison of attribute identity should be done by comparing DbAttribute objects.
Access the metadata (i.e. data about data) associated with attributes, for example: type, name, length.
Access the metadata (i.e. data about data) associated with attributes, for example: type, name, length.
Identify attributes. i.e. methods on other classes should always take a DbAttribute rather than a string as an argument to denote the attribute. Any comparison of attribute identity should be done by comparing DbAttribute objects.
Identify attributes. i.e. methods on other classes should always take a DbAttribute rather than a string as an argument to denote the attribute. Any comparison of attribute identity should be done by comparing DbAttribute objects.

DbElement class
DbAttributes
using
DbAttributeUnit -
Type of units, for example: distance or bore or none.
DbAttributeType –
Type of attribute. One of
INTEGER = 1,
DOUBLE = 2,
BOOL = 3,
STRING = 4,
ELEMENT = 5,
DIRECTION = 7,
POSITION = 8,
ORIENTATION = 9
DbAttributeQualifier – used to determine what sort of qualifier an attribute has


class contains instances of DbElement Type

This class contains instances of DbElementType for every element type in the AVEVA module. These instances may be used wherever a DbElementType is expected, for example: if a method MyMethod() takes an DbElementType, then you could write:
for example:
It is often convenient to add a using statement for these instances, for example:
MyMethod(Aveva.Core.Database.DbElementTypeInstance.EQUIPMENT);
using NOUN=Aveva.Core.Database.DbElementTypeInstance;

MyMethod(NOUN.EQUIPMENT);

DbElementType
DbElementType
MyMethod(
)
DbElementType,
using


This class contains instances of DbAttribute for every element type in the AVEVA module. These instances may be used wherever a DbAttribute is expected, for example: if a method MyMethod() takes a DbAttribute, you could write:
For example:
It is often convenient to add a using statement for these instances.
For example:
MyMethod(Aveva.Core.Database.DbAttributeInstance.XLEN);
using ATT=Aveva.Core.Database.DbAttributeInstance;

MyMethod(ATT.XLEN);

MyMethod()
DbAttribute
using


Functionality is available to manipulate the access to elements.


This section describes the DbElement class. The DbElement class is the most widely used class and it covers a large proportion of the database functionality that will be used in practise.
The methods fall into the following groups:
DbElement is a generic object that represents all database elements regardless of their type.
An instance of a DbElement may be obtained as follows:
for example.
The DbElement object encapsulates the identity of the database object. Any comparison of database objects must be done using DbElements. The DbElement has 'value' semantics for comparison purposes. i.e. comparing of two DbElements will always return true if they refer to the same element, even if they are different objects. DbElement instances should be used in all cases where the identity of an element is being passed or stored.
A DbElement can be identified externally to the AVEVA module by a combination of the ref number AND type. The ref number is a two long integer, for example: =123/4567.
A DbElement need not represent a 'valid' element. There are a number of reasons why a DbElement might be invalid:
There is a IsValid()method to test if a DbElement is valid.
If the DbElement is invalid then all attribute access and database navigation will fail for that DbElement.
The error handling techniques used are:
DbElement has the following basic methods:
ToString()- Returns the Name of the element. If unnamed, it returns the constructed name.
GetElementType()- Returns the DbElementType.
There are a number of pseudo attributes that return slight variations on name and type, as below.
Type related:
ACTTYPE
DbElementType

Type of element
AHLIS
DbElementType (200)

List of actual types in owning hierarchy
OSTYPE
DbElementType

Shortcut for "Type of owner"
TYPE
DbElementType

Type of the element, ignoring UDET
TYSEQU
int

Type Sequence Number
Name Related:
CUTNAM
String
int
Full name of element, truncated to n characters
CUTNMN
String
int
Full name of element (without leading slash) truncated to n characters
FLNM
String

Full name of the element
FLNN
String

Full name of the element (without leading slash)
ISNAMED
Bool

True if element is named
NAMESQ
String

Type. sequence number and name of element
NAMETY
String

Type and name of the element
NAMN
String

Name of the element (without leading slash)
NAMTYP
String

Type and full name of element

DbElement vess1 = DbElement.GetElement("/VESS1");
Navigation
Querying of attributes
Database modifications
Storage of rules and expressions
Comparison across sessions
Navigation
Navigation
Querying of attributes
Querying of attributes
Database modifications
Database modifications
Storage of rules and expressions
Storage of rules and expressions
Comparison across sessions
Comparison across sessions
There is a static GetElement() method with no arguments to return a 'null' DbElement.
There is a static GetElement() method which returns a DbElement given a name. This name should include the '/'.
There is a static GetElement() method which returns a DbElement given a ref (two long int array) and type. This is only needed where a reference has been stored externally to the AVEVA module.
There are many methods on various classes which return DbElements
There is a static GetElement() method with no arguments to return a 'null' DbElement.
There is a static GetElement() method with no arguments to return a 'null' DbElement.
There is a static GetElement() method which returns a DbElement given a name. This name should include the '/'.
There is a static GetElement() method which returns a DbElement given a name. This name should include the '/'.
There is a static GetElement() method which returns a DbElement given a ref (two long int array) and type. This is only needed where a reference has been stored externally to the AVEVA module.
There is a static GetElement() method which returns a DbElement given a ref (two long int array) and type. This is only needed where a reference has been stored externally to the AVEVA module.
There are many methods on various classes which return DbElements
There are many methods on various classes which return DbElements
The element is in a DB not opened.
The element has been deleted.
The element is in a DB not opened.
The element is in a DB not opened.
The element has been deleted.
The element has been deleted.

DbElement
DbElement
GetElement()
DbElement
GetElement()
DbElement
GetElement()
DbElement
DbElements
DbElement
DbElements
DbElement
DbElements
DbElement
DbElement
IsValid()
method
DbElement
DbElement
DbElement
DbElement
ToString()
GetElementType()
DbElementType
.
Type related:
DbElementType
DbElementType (200)
DbElementType
DbElementType
int
Name Related:
String
int
String
int
String
String
Bool
String
String
String
String


There are basic methods to navigate the primary hierarchy. for example, consider the following hierarchy:

If we are sitting at Zone2, we can navigate as follows:
Scanning the database is a very common operation. For this reasons there are additional iterator and filter classes that ease this task. These are described in the section on Filters/Iterators.
ALLELE
DbElement[])
DbElementType
All elements in the MDB of a particular type
CONNECTIONS
DbElement[]

Connections
CONNECTIONSH
DbElement[]

Connections for all descendants
CONNER
String
Int
Connection error message
DDEP
Int

Database depth within hierarchy (World is 0)
FRSTW
DbElement
String
Reference of first world of given DB type in current MDB
MAXD
Int

DB hierarchy depth of lowest level item beneath element
MBACK
DbElement[]
*DbElementType
Members in reverse order
MCOU
Int
*DbElementType
Number of Element Members of Given type
MEMB
DbElement[]
*DbElementType
All members, or members of specific type
OWNLST
DbElement[]

Owning hierarchy
PARENT
DbElement
*DbElementType
Reference of ascendant element of specified type
SEQU
Int

Sequence Position in Member List
TYSEQU
Int

Type Sequence Number
'*'- qualifier is optional
Standard navigation methods do not work for descending a secondary hierarchy. Pseudo attribute SMEMB must be used, for example: to get the design elements below a GPSET, you must query the SMEMB attribute on the GPSET.
Pseudo attributes relating to secondary hierarchies are:
GPPRXS
DbElement[]
Group proxy items referring to element
GROUPS
DbElement[]
GPSETs in which element occurs
SEXPND
DbElement[]
Recursive expansion of SMEMB
SITEM
DbElement
Reference from secondary hierarchy
SMEMB
DbElement[]
Immediate members in secondary hierarchy
The difference between SMEMB and SEXPND is that SEXPND allows for recursive secondary hierarchies. Where there are no recursive possibilities, SMEMB and SEXPND will be the same. The following example illustrates the difference between SMEMB and SEXPND:

In the example there are two secondary nodes S1 and S2. S1 holds element A and C, and S2 holds S1, D and G.
For S1,
SMEMB returns A,C
SEXPND returns A,C
For S2,
SMEMB returns S1,D, G
SEXPND returns A,C, D, G
using NOUN=Aveva.Core.Database.DbElementTypeInstance;

DbElement zone = DbElement.GetElement("/Zone1")
DbElement temp=zone2.Next(); // temp is now Zone3
temp=zone2->Previous(); // temp is now Zone1
temp=zone2->Owner(); // temp is now Site1
temp=zone2->FirstMember(); // temp is now Pipe1
DbElement pipe1=temp;
temp=zone2->LastMember(); // temp is now Equi1
DbElement temp=pipe1.Next(NOUN.EQUIPMENT); // temp is Equi1
DbElement temp=pipe1.Previous(); // temp is ‘null’ as there is no previous element.
      This can only be tested using the ‘IsNull’ method

using

Attribute Name
Data Type
Qualifier
Description
DbElement[])
DbElementType
DbElement[]
DbElement[]
String
Int
Int
DbElement
String
Int
DbElement[]
*DbElementType
Int
*DbElementType
DbElement[]
*DbElementType
DbElement[]
DbElement
*DbElementType
Int
Int
DbElement[]
DbElement[]
DbElement[]
DbElement
DbElement[]


The attributes available on for a DbElement will depend on its type, for example: a site will have different attributes to a branch. For this reason attributes are accessed through generic methods rather than specific methods. These generic methods pass in the identity of the attribute being queried (a DbAttribute object). There are separate methods for each attribute type (int, double etc), plus separate methods for single values or arrays.
for example:
This call returns the value of attribute XLEN. If 'myEle' is not a BOX then an exception will be raised.
If there is any doubt as to whether 'myEle' is a BOX or not, then there are a set of methods that return false if the attribute does not exists.
for example:
In addition there is a IsAttributeValid() method that can be used to test if an attribute is valid or not.
The basic mechanism works for all attributes including UDAs and pseudo attributes.
The attribute types supported are:
int, int[]
double, double[]
bool, bool[]
string, string[]
DbElement, DbElement[]
DbElementType, DbElementType[]
DbAttribute, DbAttribute[]
Position
Direction
Orientation
Expression
int, int[]
double, double[]
bool, bool[]
string, string[]
DbElement, DbElement[]
DbElementType, DbElementType[]
DbAttribute, DbAttribute[]
Position
Direction
Orientation
Expression
There are two lists of valid attributes:
Related pseudo attributes are:
Attribute Name
Data Type
Description
ATTLIST
DbElementType[]
List of all visible attributes for element
ATTRAW
DbElementType[]
List of raw attributes
PSATTS
DbElementType[]
List of pseudo attributes
RLIS
DbElementType[]
List of rules set
UDALIS
DbElementType[]
List of UDAs
UDASET
DbElementType[]
List of UDAs set
Attribute Name
Data Type
Description
ATTLIST
DbElementType[]
List of all visible attributes for element
ATTRAW
DbElementType[]
List of raw attributes
PSATTS
DbElementType[]
List of pseudo attributes
RLIS
DbElementType[]
List of rules set
UDALIS
DbElementType[]
List of UDAs
UDASET
DbElementType[]
List of UDAs set
Many attributes take a qualifier. The qualifier is the extra information to make the query. Examples of where a qualifier is used are:
The definition of what pseudo attributes take what qualifier is described in the data model reference manual.
The DbQualifier class represents the qualifier. This can hold any type of qualifier, i.e. int, double,string, DbElementType, Attribute, position, direction, orientation. It can hold multiple qualifier values, although few current attributes require multiple valued qualifiers. There is a separate method to set the WRT element.
There is a set of query routines that take a qualifier as an extra argument.
for example: to query the bore of ppoint 1:
If the attribute value is to go onto a form then the value must be formatted correctly. The correct formatting is not always obvious or available. Therefore there are special methods to return any attribute as a formatted string. This will format the attribute into the form that would appear at the command line. For example if the attribute is a position and we are working in finch unit, then something like 'W 39'4.7/16 N 59'0.85/128 U 4'0.31/128' might be returned.
The method to do this is GetAsString().
using ATT=Aveva.Core.Database.DbAttributeInstance;

double length=myEle.GetDouble(ATT.XLEN);
using ATT=Aveva.Core.Database.DbAttributeInstance;

double length;
if (!myEle.GetValidDouble(ATT_XLEN,length)) {
    // handle error in some way
}
DbQualifier qual=new DbQualifier();

qual.Add(1);
double bore=myele.GetDouble(ATT.PPBO, qual);
Note:
The methods that are called GetAttribute, GetAttributeArray are the 'getattribute' methods that return DbAttributes. Similarly the GetElement, GetElementArray methods are the 'getattribute' methods that return DbElements. This is confusing since GetElement is also the name of the method to return a DbElement given a name. We may change the names of these in the future.
Note:
There is no generalized method for setting an attribute from a string.

DbElement
DbAttribute
using
using
A
IsAttributeValid()
Note
:
GetAttribute
GetAttributeArray
DbAttributes
GetElement
GetElementArray
DbElements
GetElement
DbElement
GetAttributes()
DbElementType[]
DbElementType[]
DbElementType[]
DbElementType[]
DbElementType[]
DbElementType[]
DbQualifier
new
W 39'4.7/16 N 59'0.85/128 U 4'0.31/128
GetAsString()
Note
:


The following modifications are allowed:
When an element is modified, it is not simply the case of directly updating the database. For example, when setting an attribute the following sequence takes place:
It can be seen that making what appears to be a simple modification is actually quite complicated.
In particularly a lot of errors are possible. Errors may be generated by any of the steps 1-2 plus steps 4-8.
If an error occurs the code will raise a PdmsException. The calling code needs to allow for this.
Clarification of some of these errors is as follows:
Check that the attribute value is the right type
For example, if a text attribute then the new value must be text, for example: setting DESC to 99 will raise an error.
Check against any valid values or ranges
This will check the value against any user provided criteria stored in the dictionary DBs.
Check access control
An error will be raised if the modification is not allowed. An error will also be raised at this point if the attribute is not valid for the given element.
Check that the DB is open in write
An error will be raised if 'read only'.
Check LOCK flag
An error will be raised if the LOCK flag is true.
Do claim check, and claim if needed (and implicit claim is allowed)
An error will be raised if:
Call the legality checking routines to make sure that the modification is valid
These checks are made by the plugged in application specific code. Thus potentially any error could be raised.
If a DB has been set up to be 'implicit' the user will claim elements as needed without having to do explicit claims.
There are some methods on DbElement to claim/release individual elements or a hierarchy of elements. If working on a hierarchy of elements, and errors occur, then the system will still do what it can.
There are also methods on the MDB class to claim/release a list of elements. Performance is improved by claiming or releasing elements in bulk, thus in general the MDB methods should be used rather than the ones on DbElement.
The granularity of claim is at the level of primary element. This is described in the data management reference manual.
Pseudo Attributes Relating to Claims
CLMID
String
Unique system ID of user claiming element
CLMNUM
int
User or extract number claiming element. Extract numbers are negative
CLMTIE
DbElement[]
Reference to elements that are automatically claimed along with this element
NPDESC
DbElement[]
List of non primary offspring
OKCLA
bool
True if element may be claimed
OKCLH
Bool
True if element and hierarchy may be claimed
OKREL
bool
True if element may be released
OKRLH
Bool
True if element and hierarchy may be released
PRIMTY
Bool
True if element is primary
PRMMEM
bool
True if there are any primary elements amongst descendants
PRMOWN
DbElement
Primary owning element (will be itself if primary)
USCLHI
DbElement[]
Elements in descendant hierarchy claimed to this user
USERC
String
User name of user claiming element
USNCLH
DbElement[]
Elements in descendant hierarchy not claimed to this user

Set Attribute
Create Element
Delete Element
Copy Element
Move Element
Change Type
Set Attribute
Set Attribute
Create Element
Create Element
Delete Element
Delete Element
Copy Element
Copy Element
Move Element
Move Element
Change Type
Change Type
The DB uses explicit claims and the primary element has not been claimed.
The primary element is claimed by another user or extract.
The DB uses explicit claims and the primary element has not been claimed.
The DB uses explicit claims and the primary element has not been claimed.
The primary element is claimed by another user or extract.
The primary element is claimed by another user or extract.

Set Attribute
Create Element
Delete Element
Copy Element
Move Element
Change Type
Set Attribute
Create Element
Delete Element
Copy Element
Move Element
Change Type
Check that the attribute value is the right type
Check against any valid values or ranges
Check access control
Check that the DB is open in write
Check LOCK flag
Do claim check, and claim if needed (and implicit claim is allowed)
Call the legality checking routines to make sure that the modification is valid
DbElement
DbElement
Pseudo Attributes Relating to Claims
String
int
DbElement[]
DbElement[]
bool
Bool
bool
Bool
Bool
bool
DbElement
DbElement[]
String
DbElement[]


Database expressions are PML1 expressions, for example: (XLEN * 1000). Expressions are of the following type:
Database expressions are stored in various places in the AVEVA module as follows:
There is a DbExpression class to hold an expression. An DbExpression may be obtained in one of the following ways:
Having got an DbExpression there are two things that can be done with it:
The methods to evaluate an expression against an element are on the DbElement class. There are different methods depending on the expected result of the expression. The method names start with 'Evaluate'. The method that returns a double has an argument for the units (distance/bore/none). The result will always be in millimetres (mm), for example:
In this case the core system can work out that it is a distance, since DIAM is a distance. Thus although we specified that it was a distance, it was not strictly needed. Thus if the distance units were inch or finch then the '+2' would be interpreted as '+2inches'.
However consider:
In this case we do not know if "10" is 10mm or 10 inches. We must tell the system that it is a 'distance' unit. The system then interrogates the current distance units to return the result. If the current distance units is mm, then dval will be 10.0. If the current distance units is inch/finch then "10" is interpreted to mean 10 inches and is hence returned as 254.
PML.NET rules consist of an expression and a dynamic/static flag. When constructing a rule, the expression type is also needed.
There are methods on DbElement to:
NRULEE
Int

Number of rule inconsistencies on element
RCOU
Int

Number of rules on element
RULEER
String
int
Text of "nth" rule error
RULSET
DbAttribute[]

List of rules set

DbExpression expr = DbExpression.Parse("DIAM OF PREV + 2");
double dval;

DbAttributeUnit units = DbAttributeUnit.DIST;
dval = nozz1.EvaluateDouble(expr4, units);
DbExpression expr = DbExpression.Parse("10");
double dval;

DbAttributeUnit units = DbAttributeUnit.DIST;
dval = nozz1.EvaluateDouble(expr4, units);
Double
DbElement
Bool
String
Position
Direction
Orientation
Double
Double
DbElement
DbElement
Bool
Bool
String
String
Position
Position
Direction
Direction
Orientation
Orientation
As part of a rule
Parameterization of the catalogue
As part of a rule
As part of a rule
Parameterization of the catalogue
Parameterization of the catalogue
Use the static method internalParse() that creates a DbExpression from a string, for example: internalParse("XLEN * 100")
Retrieve an expression from a rule
Retrieve an expression from a catalogue parameter
Use the static method internalParse() that creates a DbExpression from a string, for example: internalParse("XLEN * 100")
Use the static method internalParse() that creates a DbExpression from a string, for example: internalParse("XLEN * 100")
Retrieve an expression from a rule
Retrieve an expression from a rule
Retrieve an expression from a catalogue parameter
Retrieve an expression from a catalogue parameter
Set a rule for any attribute.
Get a rule for any attribute
Evaluate a rule
Verify that the rule result is up to date
Set a rule for any attribute.
Set a rule for any attribute.
Get a rule for any attribute
Get a rule for any attribute
Evaluate a rule
Evaluate a rule
Verify that the rule result is up to date
Verify that the rule result is up to date
Note:
If the value is required to be formatted for output, then it must be converted back in all cases. A method will be added to return values in local units at a later point.

internalParse()
DbExpression
internalParse("XLEN * 100")
double
double
Note
Int
Int
String
int
DbAttribute[]


There are no explicit methods exposed in C# which cover comparison across sessions. It is not currently possible to set the comparison date in C#.
There are however a number of pseudo attributes that can be accessed as follows:
ATTMOD
Bool
DbAttribute
True if specified attribute has been modified this session
ATTMODC
bool
DbAttribute
True if specified attribute has been modified since comparison date
ATTMODLIST
DbAttribute[]
int
List of attributes modified since given session
ATTMODLISTC
DbAttribute[]

List of attributes modified since comparison date
CRINFO
string

DB creation information
DBSESS
int

Last DB session
ELECRE
bool
int
True if created since given session
ELECREC
bool

True if created since comparison date
ELEDEL
bool
int
True if deleted since given session
ELEDELC
bool

True if deleted since comparison date
ELEMOD
bool
int
True if modified since given session
ELEMODC
bool

True if modified since comparison date
EXMOD
bool

True if element modified in this extract
HIST
Int[]
DbAttribute
History of sessions in which element or specified attribute were made
LASTM
string
DbAttribute
Date of last modification
MSESS
int
DbAttribute
Last session number
PRVSES
int
int
Previous Session to that specified
RULEMOD
bool
DbAttribute
True if rule modified this session
RULEMODC
Bool
DbAttribute
True if rule modified since comparison date
RULEMODLIST
DbAttribute[]
int
List of rules modified since given session
RULEMODLISTC
DbAttribute[]

List of rules modified since comparison date
SESCLA
int

Session Of Claim
SESSC
string
int
Comment for specified session
SESSCA
Int[]

List of pairs of DB number, last session number for all referenced DBs
SESSCH
Int[]

As for SESSCA, but searches all descendants for referenced DBs
SESSD
string
int
Date of specified Session
SESSM
int
DbAttribute
Session Of Last Modification
SESSNO
int

Current opened Session
SESSU
string
int
User creating specified session
USERM
string
DbAttribute
User making last modification

Bool
DbAttribute
bool
DbAttribute
DbAttribute[]
int
DbAttribute[]
string
int
bool
int
bool
bool
int
bool
bool
int
bool
bool
Int[]
DbAttribute
string
DbAttribute
int
DbAttribute
int
int
bool
DbAttribute
Bool
DbAttribute
DbAttribute[]
int
DbAttribute[]
int
string
int
Int[]
Int[]
string
int
int
DbAttribute
int
string
int
string
DbAttribute


The DBElementCollection class can be used to iterate through the database hierarchy. The iterator is created with a root element and an optional filter. There are then methods to step through the hierarchy and return the element at the current location.
For example: to look for all nozzles below a given element
The collection can then be iterated through using foreach
The iterator class has been written to avoid unnecessarily scanning parts of the database that will not match the filter, for example: if looking for all boxes then the iterator will not bother to look below pipes.
TypeFilter filt = new TypeFilter(DbElementTypeInstance.NOZZLE);

DBElementCollection collection;

collection = new DBElementCollection(ele, filt);

foreach (DbElement ele in collection)
{
…. Do something
}

DBElementCollection
TypeFilter
new
TypeFilter(DbElementTypeInstance
DBElementCollection
new
DBElementCollection
ele
foreach
(
DbElement
in
collection)


There are a variety of ready built filter classes available. The main ones are:
TypeFilter - True for given Element type(s)
AttributeFalseFilter - True if given attribute is false
AttributeTrueFilter - True if given attribute is true
AttributeRefFilter - True if given attribute value matches given DbElement
AndFilter - AND two existing filters
OrFilter - OR two existing filters
BelowFilter - Filter to test if element is below an element for which the given filter is true.

TypeFilter
AttributeFalseFilter
AttributeTrueFilter
AttributeRefFilter
AndFilter
OrFilter
BelowFilter


In the Dabacon schema we can define an attribute to be an indexed attribute. Indexed attributes go into a Dabacon table.
Tables consist of a list of key/value pairs. The key may be a string (ntable), integer (itable) or reference (ftable). The 'value' part of the pair is always the refno of the element having that attribute value, for example: internally a name table may look something like:
…..
Janet = 123/456
John = 321/543
Jonathon = 111/321
…
Thus for a given name, the corresponding element can rapidly be found without having to scan the entire Multiple DataBase (MDB).
The keys in a name table must be unique. Integer and reference tables may contain the same key many times, for example: internally a reference table may look like:
….
=123/456 =234/555
=123/456 =222/333
=123/456 =211/999
=123/458 =203/909
In the above table, element =123/456 has appeared in the table three times. This means that three different elements were all referencing =123/456 for this particular attribute. This is common, for example: catalogue references are reference tables, and for these there may be hundreds of elements referencing the same catalogue component. A further point worth noting with respect to tables:
Each Database (DB) has its own table. The entries in that table are for 'values' in that DB. Thus for the above ftable, =234/555 etc must be in this DB. However =123/456, =123/458 may be in a different DB. Indeed there may well be further references to =123/458 from other DBs. Hence to find all references to =123/456 we need to check the tables in each opened DB.
Each Database (DB) has its own table. The entries in that table are for 'values' in that DB. Thus for the above ftable, =234/555 etc must be in this DB. However =123/456, =123/458 may be in a different DB. Indeed there may well be further references to =123/458 from other DBs. Hence to find all references to =123/456 we need to check the tables in each opened DB.
Each Database (DB) has its own table. The entries in that table are for 'values' in that DB. Thus for the above ftable, =234/555 etc must be in this DB. However =123/456, =123/458 may be in a different DB. Indeed there may well be further references to =123/458 from other DBs. Hence to find all references to =123/456 we need to check the tables in each opened DB.


C# classes to access directly to the Dabacon Tables

There are C# classes that enable direct access to the Dabacon tables. The classes are defined as follows:
NameTable - for iterating through name tables
RefTable - for iterating through reference tables
IntTable - for iterating through integer tables
These classes work on a single DB. In most cases, we really want to iterate through all DBs in the MDB as if it was one table. Thus for integer and name tables there are iterator classes that go across the whole MDB as follows:
MdbNameTable - for iterating through a name table across entire MDB
MdbIntTable - for iterating through an integer table across entire MDB
There is no method for iterating through a reference table since the order of references in a table is not meaningful.
There are also methods to return all entries for a given key. This is particularly useful for reference tables; these are methods of the MDB class.
In C# there is a NameTable class. An example of C# code that looks for all names starting with the letter 'B' is as follows:
Dabacon allocates search tokens when scanning tables. It has a limited number of search tokens. If you get to the end of the table then the token is freed automatically. However if you stop the search before you get to the end then you must explicitly free the token.
The IDispose method is used to free the underlying Dabacon token. Therefore ALWAYS scan the Dabacon table within a 'using' block to make sure that the Dispose method is called. If the underlying token is not freed then errors will be output to the AVEVA module command line of the form:
The error generating code does not actually free the tokens. So typically you will see the number climb as more tokens are used up and not freed. The messages will be generated until the database is closed.
string nam1=new string("/B");
string nam2=new string("/C");
NameTable ntable = new MdbNameTable(db, DBAttribute.NAME, nam1, nam2);

using (ntable)

{
   foreach (Element ele in ntable)

   {
   // Do something here with each element
   }
}
"xx dabacon search tokens - Expected none "

NameTable
RefTable
IntTable
MdbNameTable
MdbIntTable
new
using

foreach
in


The Miltiple DataBase (MDB) class exposes methods that act on the currently opened MDB. This is a singleton class. It contains methods to
Related pseudo attributes are:
OKDROP
bool
True if element may be dropped
OKRLEX
bool
True if element may be extract released

Open/close an MDB.
Save work / quit work.
Query claims.
Claim/release elements
Extract operations, for example: flush, refresh, extract claim, extract release, extract drop.
Get opened DataBases (DBs).
Return an element(s) of a given name.
Return elements with matching values in name and integer tables (as described in previous section.
Open/close an MDB.
Open/close an MDB.
Save work / quit work.
Save work / quit work.
Query claims.
Query claims.
Claim/release elements
Claim/release elements
Extract operations, for example: flush, refresh, extract claim, extract release, extract drop.
Extract operations, for example: flush, refresh, extract claim, extract release, extract drop.
Get opened DataBases (DBs).
Get opened DataBases (DBs).
Return an element(s) of a given name.
Return an element(s) of a given name.
Return elements with matching values in name and integer tables (as described in previous section.
Return elements with matching values in name and integer tables (as described in previous section.


When an Multiple Database (MDB) is opened, a Database (DB) class instance is created for each opened DB.
The functionality offered by this class falls into the following categories:
ACCEDB
string

DB access
CLAIM
String

Implicit or explicit claims
CLCCNT
int

Claim list changes count
CSESS
String
int
Comment entered for specified session
DACC
String

Database access
DBLC
DbElement[]

List of LOCs belonging to a DB
DCLA
String

Database claim mode
DSESS
String
int
Date of specified session
EXPIRY
String

Protected DB Expiry date
EXTALS
DbElement[]

Extract ancestors
EXTCLS
DbElement[]

Extract children
EXTDES
DbElement[]

Extract descendants
EXTFAM
DbElement[]

Extract family
FILENAME
String

DB filename
FOREIGN
string

Originating project
HCCNT
int

Header/Extract list changes count
ISDBFR
bool

True if database is foreign
ISDRDB
Bool

True if database has drawings
ISWORK
bool

True if a working extract
LINKSN
int

Linked session on parent extract
LPROT
bool

Protected DB Flag
MDBCLS
DbElement[]

List of MDBs in which DB is current
MDBLS
DbElement[]

List of MDBs to which DB belongs
NACCNT
int

Non-additive changes count
NAMEDB
string

DB name
NXTDBN
int

Next DB number
NXTEXN
int

Next DB extract number
NXTFDB
int

Next DB file and DB number
NXTFLN
int

Next DB file number
PSESS
int
int
Previous session number
SIZEDB
int

Size of DB
STPDBS
DbElement[]

Stamps containing db
STPSES
Int[]

Sessions used in at least one stamp
STYPDB
string

DB sub type
TYPEDB
string

DB type
USESS
string
int
User creating session
In addition for any DbElement in any DB, the following pseudo attributes provide information on the current DB:
DBAC
String

DB Access, MULTIWRITE or UPDATE
DBCL
String

DB Claim
DBCNTL
Bool

True if element is in a control DB
DBEXNO
int

DB Extract Number
DBFI
String

DB filename
DBFN
int

DB file number
DBNA
String

DB name
DBNU
int

DB Number
DBREF
DbElement

Reference of DB element
DBTY
String

DB type (DESI, CATA etc)
DBVAR
Bool

True if element is in a variant DB
DBWRITE
Bool

True if element is in a writable DB
WDBNA
STRING

Working DB name

Query the properties of the DB, for example: number, MULTIWRITE or not
Returning the world element for that DB
Session information, for example: when was the session written and by whom. There is a DbSession object that holds details on a database session.
Return the DbElement in the system DB that represents this DB. This DbElement can then be used to query system attributes and additional pseudo attributes. The additional pseudo attributes available on the DbElement representing the DB are described below:
Query the properties of the DB, for example: number, MULTIWRITE or not
Query the properties of the DB, for example: number, MULTIWRITE or not
Returning the world element for that DB
Returning the world element for that DB
Session information, for example: when was the session written and by whom. There is a DbSession object that holds details on a database session.
Session information, for example: when was the session written and by whom. There is a DbSession object that holds details on a database session.
Return the DbElement in the system DB that represents this DB. This DbElement can then be used to query system attributes and additional pseudo attributes. The additional pseudo attributes available on the DbElement representing the DB are described below:
Return the DbElement in the system DB that represents this DB. This DbElement can then be used to query system attributes and additional pseudo attributes. The additional pseudo attributes available on the DbElement representing the DB are described below:

string
String
int
String
int
String
DbElement[]
String
String
int
String
DbElement[]
DbElement[]
DbElement[]
DbElement[]
String
string
int
bool
Bool
bool
int
bool
DbElement[]
DbElement[]
int
string
int
int
int
int
int
int
int
DbElement[]
Int[]
string
string
string
int
String
String
Bool
int
String
int
String
int
DbElement
String
Bool
Bool
STRING


The database events fall into the following groups:
General capture of Database changes.
Writing Pseudo attributes for User Defined Attributes (UDAs).
DB/MDB related events.
General capture of Database changes.
General capture of Database changes.
Writing Pseudo attributes for User Defined Attributes (UDAs).
Writing Pseudo attributes for User Defined Attributes (UDAs).
DB/MDB related events.
DB/MDB related events.


The generalised mechanism in C# is as follows:
There is a delegate to define the event signature.
There is a method to add a delegate to the list of event handlers to be called.
There is a delegate to define the event signature.
There is a delegate to define the event signature.
There is a method to add a delegate to the list of event handlers to be called.
There is a method to add a delegate to the list of event handlers to be called.


Dblayer maintains a change list of Database(DB)

DBlayer maintains a change list of Database (DB) changes. Users can subscribe to this list of changes.
The list of changes is encapsulated in the DbUserChanges class. The DbUserChanges class has methods to determine what changes have been made, for example: elements created or deleted or modified.
The delegates are:
To add a subscriber (handler), the method is:
This will be in the DbEvents class.
The subscribers receive a DbUserChanges class instance which has a list of elements changed and what the changes are.
The events are fired as follows:
The event will only be fired if database changes have been made.
public delegate void ChangeEventHandler(DbUserChanges changes);

public static void AddChangeEventHandler(ChangeDelegate plug)

At the end of running in a Programmable Macro Language (PML) macro
After the execution of an AVEVA module specific command on the command line
When any action on a form has completed.
At the end of running in a Programmable Macro Language (PML) macro
At the end of running in a Programmable Macro Language (PML) macro
After the execution of an AVEVA module specific command on the command line
After the execution of an AVEVA module specific command on the command line
When any action on a form has completed.
When any action on a form has completed.

public delegate
public static void


Calculate the value of pseudo attributes

Code can be plugged in to calculate the value of pseudo attributes. The code to do this must be registered in the AVEVA module by passing in a C# delegate.
Code can be registered in two ways:
The same UDA may have multiple delegates registered for different element types.
There is a different delegate for each attribute type, for example: for integer attributes the delegate is:
These are defined in the DbPseudoAttribute class.
The user must write a method that matches the method signature of the delegate, for example: to write pseudo attribute code for a 'double' attribute, the user must write a method that has the signature defined by 'GetDoubleDelegate'. for example, a method that takes a DbElement, a DbAttribute, int and returns a double.
For example: the following method would be valid:
An instance of the delegate containing the method must then be created and registered with the AVEVA module.
There are separate methods to register the different types of delegates. There are also separate methods to add a plugger for a particular element type, for example: the two methods to add a GetDoubleDelegate are:
An example of registering a delegate is:
Code may be plugged by User Defined Element Type (UDET) as well as the base type. The following criteria are used to locate the right plugged code:
for example: you could add three delegates to calculate :WEIGHT. You could add one that calculates the :WEIGHT on a :MYELE, one that calculates the :WEIGHT of SCTN and one that calculates WEIGHT for any other element for which :WEIGHT is valid.
A delegate only needs adding once at start up.
The events do not allow for errors. Thus if the value can not be calculated then the pseudo attribute code should return a sensible default.
public delegate double GetDoubleDelegate(DbElement ele, DbAttribute att, int qualifier);

// Double delegate for UDA
static private double VolumeCalculation(DbElement ele,DbAttribute

                         att,int qualifier)
{
 // calculate the volume by multiplying the lengths along each side
 double x=ele.GetDouble(ATT.XLEN);

 double y=ele.GetDouble(ATT.YLEN);

 double z=ele.GetDouble(ATT.ZLEN);

 // Result of UDA must be returned
 return (x * y * z);

}
public static void AddGetDoubleAttribute(DbAttribute att,GetIntDelegate plug)

public static void AddGetDoubleAttribute(DbAttribute att, DbElementType type, GetIntDelegate plug)

using System;

using NOUN=Aveva.Core.Database.DbElementTypeInstance;

using Ps=Aveva.Core.Database.DbPseudoAttribute;

namespace Aveva.Core.Shared.Tests

{
 static public void RegisterDelegate()

 {

  // get uda attribute
  DbAttribute uda=DbAttribute.GetDbAttribute(":VOLUME");

  // Create instance of delegate containing "VolumeCalculation" method
  Ps.GetDoubleDelegate dele=new Ps.GetDoubleDelegate(VolumeCal\-culation);

  // Pass delegate instance to core PDMS. This will be invoked later
     // when :VOLUME is queried.
      // In this case registry for all valid element types.
  Ps.AddGetDoubleAttribute(uda,dele);

   }

}

public delegate
'GetDoubleDelegate'
DbElement
DbAttribute
// Double delegate for UDA
static private double

// calculate the volume by multiplying the lengths along each side

double

double

double

// Result of UDA must be returned

return
GetDoubleDelegate
public static void
public static void

using
using
using
namespace

static public void

// get uda attribute

// Create instance of delegate containing "VolumeCalculation" method

=new

// Pass delegate instance to core PDMS. This will be invoked later
     // when :VOLUME is queried.
      // In this case registry for all valid element types.


The following events can be captured:
Except for quit, the pre actions are really called post action but with the Database (DB) in the pre action state. The pre action is only called if the action succeeds.
Most of the pre and post actions fall into just two categories:
The interested parties are different in the two cases. When changing the database file, the interested parties are 3rd party systems outside of the AVEVA module. When changing our view of the database it is the current session that needs to reflect the changes, for example: update the 3D graphics and explorer.
The events raised reflect this split.
The events are:
CommitPending - This is called to commit any outstanding change to the database. It is called prior to setmark, undo, redo, Savework, quit, Getwork.
ClearCache() - This will be called after doing a temporary switch to a different session in a DB, or after doing a Getwork, undo, redo, quit.
CommitPending - This is called to commit any outstanding change to the database. It is called prior to setmark, undo, redo, Savework, quit, Getwork.
CommitPending - This is called to commit any outstanding change to the database. It is called prior to setmark, undo, redo, Savework, quit, Getwork.
ClearCache() - This will be called after doing a temporary switch to a different session in a DB, or after doing a Getwork, undo, redo, quit.
ClearCache() - This will be called after doing a temporary switch to a different session in a DB, or after doing a Getwork, undo, redo, quit.
Pre and Post events for local changes. i.e. changes affecting the current view of the data. These will be Getwork, undo, redo.
Pre and Post events for changes affecting the data on the DB. These will be Savework, refresh, drop, flush, refresh. These will pass the list of changes. For 'global' DBs, if the parent extract is at a different location, the flush event will be raised by the child extract.
Pre and Post events for local changes. i.e. changes affecting the current view of the data. These will be Getwork, undo, redo.
Pre and Post events for local changes. i.e. changes affecting the current view of the data. These will be Getwork, undo, redo.
Pre and Post events for changes affecting the data on the DB. These will be Savework, refresh, drop, flush, refresh. These will pass the list of changes. For 'global' DBs, if the parent extract is at a different location, the flush event will be raised by the child extract.
Pre and Post events for changes affecting the data on the DB. These will be Savework, refresh, drop, flush, refresh. These will pass the list of changes. For 'global' DBs, if the parent extract is at a different location, the flush event will be raised by the child extract.
Post claim/release events
Post failed Getwork/Savework
Post claim/release events
Post claim/release events
Post failed Getwork/Savework
Post failed Getwork/Savework
Note:
ClearCache may be called thousands of times within a single operation. Thus any event handlers must be fast.
Note:
In this case the flush could still fail at the parent. Alternatively the daemon needs to raise the flush event.

CommitPending
ClearCache()
Note
:

ClearCache
Note
:


Real dimensioned quantities may be created or returned as objects of type DbDouble which have a dimension, DbDoubleDimension, current units, DbDoubleUnits, and a real value which may be presented as a string using a format object, DbFormat. Standard dimensions and units are defined by the enumerated types DbDimension and DbUnits returned by DbDoubleDimension and DbDoubleUnits respectively. The DbElement Get/Set interface supports both undimensioned and dimensioned attributes which may be formatted using the DbFormat object. The following classes are available in the Aveva.Core.Database interface.


Represents a standard or compound unit constructed via static constructors. For example, construct a compound unit from an expression
or construct a standard unit from a standard enumeration
There is a static method to get all the defined standard and compound units
and properties to get the description, dimension, conversion factor etc. For example, get the dimension of given units
DbDoubleUnits u1 = DbDoubleUnits.GetUnits("kg.m.s-2");

DbDoubleUnits u1 = DbDoubleUnits.GetUnits(DbUnits.MM);

DbDoubleUnits[] units = DbDoubleUnits.AllUnits();

DbDimension d1 = DbDoubleUnits.GetUnits(DbUnits.MM).Dimension;

DbDoubleUnits
DbDoubleUnits
kg.m.s-2
DbDoubleUnits
DbDoubleUnits
(
DbUnits
DbDoubleUnits
DbDoubleUnits
DbDimension
DbDoubleUnits
(
DbUnits


Enumeration of standard units. For example:
DbUnits.KG

DbUnits


Represents a standard or compound dimension constructed via static constructors. For example, construct a compound dimension from an expression
or construct a standard dimension from a standard enumeration
There are properties to get the current units for given dimension, all units for given dimension etc. For example, get all the units of given dimension
DbAttribute also has a property, Dimension, which returns the dimension of given attribute. For example,
DbDoubleDimension d1 = DbDoubleDimension.GetDimension("volt/m");

DbDoubleDimension d1 = DbDoubleDimension.GetDimension(DbDimension.DIST);

DbDoubleDimension mass = DbDoubleDimension.GetDimension(DbDimension.MASS);

DbDoubleUnits[] massUnits = mass.Units;

DbAttribute ud1 = DbAttribute.GetDbAttribute(":UD1");

DbDoubleDimension dimension = ud1.Dimension;

DbDoubleDimension
DbDoubleDimension
volt/m
DbDoubleDimension
DbDoubleDimension
DbDimension
DbDoubleDimension
DbDoubleDimension
DbDimension
DbDoubleUnits
DbAttribute
DbAttribute
:UD1
DbDoubleDimension


Enumeration of standard dimensions. For example
DbDimension.MASS

DbDimension


Represents a real dimensioned quantity which can be constructed from an expression and/or a format or returned from DbElement. For example, create a DbDouble from a real value
or create a DbDouble from a string expression
or get a dimensioned attribute from DbElement as a DbDouble
DbDouble's may also be used to set dimensioned attributes. For example, setting the HBOR of a branch
Quantities of dimension BORE may be created as follows from a real value
or a string expression and a format
returning the nearest nominal bore depending on the current BORE units. There are also properties to return the units, dimension etc. For example, get the units of given DbDouble
To return a formatted string, For example
and to convert to different units
DbDouble also implements the expected binary operator overloads '+', '-', '\', '*', '==', '!=', '<', '<=', '>' and '>=' allowing arithmetic operations and comparison of dimensioned quantities. For example, adding 2 quantities of the same dimension together
DbDouble d1 = DbDouble.Create(1.0);

DbDouble d1 = DbDouble.Create("1.0kg");

DbElement bran = DbElement.GetElement("/100-B-1-B1");

DbDouble hbor = bran.GetDbDouble(DbAttributeInstance.HBOR);

DbElement bran = DbElement.GetElement("/100-B-1-B1");

DbDouble hbor = DbDouble.Create("300", fbore)

bran.SetAttribute(DbAttributeInstance.HBOR, hbor);

DbDouble bore = DbDouble.CreateBore(300);

DbFormat fbore = DbFormat.Create();

fbore.Dimension = DbDoubleDimension.GetDimension(DbDimension.DIST);

fbore.Units = DbDoubleUnits.GetUnits(DbUnits.FINC);
DbDouble bore = DbDouble.CreateBore("12", fbore);

DbDouble d1 = DbDouble.Create("2m");

DbDoubleUnits u1 = d1.Units;

DbFormat ftemp = DbFormat.Create();

ftemp.Dimension = DbDoubleDimension.GetDimension(DbDimension.TEMP);

ftemp.Units = DbDoubleUnits.GetUnits("degRankine");

ftemp.Label = "degRan";

DbDouble t1 = DbDouble.Create("3 celsius");

String tempStr = t1.ToString(ftemp);

DbDouble d1 = DbDouble.Create("1kg");

DbDouble d2 = d1.ConvertUnits(DbDoubleUnits.GetUnits(DbUnits.LB));

d1 = DbDouble.Create("1 kg");

d2 = DbDouble.Create("2.2046 lb");

d3 = d1 + d2;

DbDouble
DbDouble
DbDouble
DbDouble
1.0kg
DbElement
DbElement
/100-B-1-B1
DbDouble
(
DbAttributeInstance
DbElement
DbElement
/100-B-1-B1
DbDouble
DbDouble
300
(
DbAttributeInstance
DbDouble
DbDouble
300
DbFormat
DbFormat
DbDoubleDimension
DbDimension
DbDouble
DbDouble
12
DbDouble
DbDouble
2m
DbDoubleUnits u1
DbFormat
DbFormat
DbDoubleDimension
DbDimension
DbDoubleUnits
degRankine
degRan
DbDouble
DbDouble
3 celsius
String
DbDouble
DbDouble
DbDouble
DbDoubleUnits
(
DbUnits
DbDouble
1 kg
DbDouble
2.2046 lb


Arithmetic errors or errors constructing DbDouble's will throw a PdmsException containing the error message. For example, adding 2 quantities of different dimensions together will throw a PdmsException which can be caught
d1 = DbDouble.Create("1 kg");

d2 = DbDouble.Create("2 mm");

try
{
   d3 = d1 + d2;
}
catch (PdmsException ex)

{

}

DbDouble
1 kg
DbDouble
2 mm
try
catch
(
PdmsException


This object allows formatting of DbDouble's as a string having properties to set the dimension, decimal points, label etc. For example, formatting a temperature
or constructing a DbDouble from a string and given format
A DbFormat object has a property that is a pointer to another DbFormat. This format will be used (delegated to) in toString type operations if the value produce by the current DbFormat is less than one.
Delegation can continue along a chain formatting the quantity to ever smaller units. All these format objects must be consistent dimension and progressively smaller units.
t1 = DbDouble.Create("0 celsius");

DbFormat tempFmt = DbFormat.Create();

tempFmt.Dimension = DbDoubleDimension.GetDimension(DbDimension.TEMP);

tempFmt.Units = DbDoubleUnits.GetUnits(DbUnits.CELSIUS);

tempFmt.DecimalPoints = 1;
tempFmt.Label = "degC";
string tempStr = t1.ToString(tempFmt);

DbFormat f1 = DbFormat.Create();

f1.Dimension = DbDoubleDimension.GetDimension(DbDimension.DIST);

f1.Units = DbDoubleUnits.GetUnits(DbUnits.INCH);

DbDouble d1 = DbDouble.Create("1", f1);

DbDouble
0 celsius"
DbFormat
DbFormat
DbDoubleDimension
(
DbDimension
DbDoubleUnits
DbUnits
string
DbFormat
DbFormat
DbDoubleDimension
.GetDimensio
DbDimension
DbDoubleUnits
(
DbUnits
DbDouble
DbDouble


PML .NET allows you to instantiate and invoke methods

Programmable Macro Language (PML) .NET allows you to instantiate and invoke methods on .NET objects from PML proxy objects. PML proxy class definitions are created from .NET class definitions at run time. These proxy classes present the same methods as the .NET class which are described using custom attributes. Proxy methods are passed arguments of known types which are marshalled to the corresponding method on to the .NET instance. The PML proxy objects behave just like any other PML object.


Programmable Macro Language (PML) callable assemblies are loaded by the AVEVA module using the IMPORT syntax. Assemblies may be defined in potentially any .NET language, for example managed C++, C# or VB.NET. The PML.NET Engine loads a given assembly using reflection. The assembly may be located in the %AVEVA_DESIGN_EXE% directory, a subdirectory below %AVEVA_DESIGN_EXE% a mapped drive or on a UNC path. When the assembly is loaded PML class definitions are created for each PML callable class within the assembly. The PML.Net Engine only loads assemblies which are marked with the custom attribute PMLNetCallable. Only classes and methods which are marked as PMLNetCallable are considered. In order to create a valid PML Proxy class definition the .NET class and its methods must adhere to certain rules. Once an assembly has been loaded instances of PMLNetCallable classes may be created. No additional code to interface between PML and .NET is necessary. This is provided by the PMLNetEngine.


The diagram below shows how AVEVA modules may be customized using PML.NET. A number of .NET API's are available which allow access to the current database session, drawlist, geometry and other functionality. Users are able to write their own managed code which accesses the AVEVA module via these C# API's. It is not possible to directly call PML from C#. However there is an event mechanism which allows PML to subscribe to events raised from C# (these are shown in dashed lines below). Events are also raised when the database changes and can be subscribed to from C# (also shown in dashed lines). In this example the external C# assemblies share the same database session as Design i.e. they run in the same process and therefore see the same data.

For example: the sequence:
will give an error.
In order to identify and load a particular class definition the PML proxy class is assumed to have the same name as the .NET class (PML callable classes must be case independent). This class name is passed to the PMLNetEngine which creates the .NET instance.
For example:
creates an instance of the .NET class netobject. To specify in which assembly this class is defined and resolve any name clashes the user needs to also specify the namespace in which the .NET class is defined using the following syntax:
Where <string> is the namespace in which the class is defined.
For example:
The namespace is considered to be case independent. This namespace will remain current until it goes out of scope, for example: at end of macro. When the user types:
then all namespaces in the current scope will be searched to find a match. In this example, if 'Aveva.Core. PMLNetExample' is not currently in scope, then the error:
will be raised.
Object names can consist of any alpha but not numeric characters (this restriction is imposed by PML). They are treated as case-independent. However, it is no longer necessary to define them in upper case - any mixture of upper and lower case letters will have the same effect.
The query methods on an object have been enhanced as follows:
(a) Querying an object will show the namespace name as well as the object name:
For example:
(b) There is a new query method to list all the methods of an object (including constructors)
For example:
(c) A new query:
lists the namespaces currently in scope.
There is a new global method on all objects:
which returns a list of the methods on the object as an array of strings.
For example:
returns:
Before an instance of a .NET object can be instantiated the assembly containing the class definition must be loaded. This is done using the IMPORT syntax as follows
Where <string> is the case-independent name of the assembly
Only PML variables of the following types may be passed to methods on .NET classes. In the table below the PML variable type is in the left column and the .NET equivalent variable type is in the right column. Data is marshalled in both directions between PML and .NET by the PMLNetEngine.
REAL
double
STRING
string
BOOLEAN
bool
ARRAY (these can be sparse and multi-dimensional)
Hashtable - The Key must be numeric (integer of double) to match the PML Array index which is always REAL. An error will be raised during execution if this is not the case.
OBJECT Any existing PML.NET instance
PMLNetCallable class
Arguments to PML Proxy methods are passed by reference so can be in/out parameters (in .NET output arguments must be passed by reference).
PML Gadgets and DB elements have reference semantics when they are copied whereas all other objects have value semantics when they are copied. This is controlled by the Assign() method on the .NET class. So, for example if the Assign() method here copies the value then
for example, !a and !b do not point to the same object.
In order to perform either a shallow or deep copy of the member data inside the .NET class the Assign() method must be defined on the .NET class (see rules). This is analogous to overriding the operator "=" in C++.
Overloading of methods is supported for all variable types in PML so a .NET Proxy can be created from a .NET class which has overloaded methods.
The custom attribute [PMLNetCallable()] is used to describe the PML interface for a .NET class. This metadata allows the PML callable assemblies to be self-describing. This clearly defines the class and allows an assembly to expose a subset of its public interface to PML. The PMLNetEngine uses this metadata to decide which .NET class definitions can be created in PML. Reflection is used to load an assembly and create PML class definitions. All classes and methods for which PML Proxy class definitions will be created must be marked as PMLNetCallable. The assembly itself must also be marked as PMLNetCallable.
So, a PML callable .NET class in C# looks like this:
This class has a default constructor and a single method. Both the constructor and method are marked as PMLNetCallable along with the class itself.
The assembly itself must also be marked as PMLNetCallable. This is normally done in the AssemblyInfo file as follows
In PML there is no concept of private members or methods - everything is public. Access to public data in .NET must be via properties or get/set accessor methods. Properties in .NET class are defined as get and set methods in PML. So, for example the following PMLNetCallable property in .NET
would have the following Proxy methods in PML
PML variables are of two kinds: global and local. Global variables last for a whole session (or until you delete them). A local variable can be used only from within one PML function or macro. The lifetime of the .NET instance is controlled by the scope of the PML proxy.
Classes can have any number of overloaded constructors but must have a default constructor which is marked as PMLNetCallable. The PML Proxy constructor instantiates an instance of the underlying .NET class. When the proxy goes out of scope the destructor destroys the underlying .NET instance.
The string() method is available on all PML objects. For a .NET Proxy this will call the ToString() method on the .NET instance. If the ToString() method is overridden on the .NET class then this will be called.
PML is case independent, so it is not possible to have MyMethod() and MYMETHOD() in .NET. PML will report non-unique object/method names.
Doubles are used in PML.NET to store reals and ints so doubles must be used in .NET (integers are not available in PML)
Events on PML.NET objects may be subscribed to from PML. A PML callback on a particular instance may be added to an event on another PML.NET instance. Events are defined by a .NET component by associating the delegate PMLNetEventHandler with the event. This delegate has the signature
Where args is an array of event arguments of any PML.NET type (see table of valid types). The following code associates this delegate with an event
This event can then be caught in Programmable Macro Language (PML) by adding an appropriate callback to the instance raising the event
Where
At some later time the event handler may be removed
where !handle is the handle of the PML.NET delegate returned by addeventhandler().
Netcallback is a PML object defined as
Exception handling is placed around the Invoke method to handle .NET method invocation exceptions like TargetException, ArgumentException etc. The result of catching such an exception is to ultimately return a PMLError object from PMLNetProxy::Invoke() which results in a PML exception (1000,n) being thrown where 1000 is the module number for PML.NET. .NET can throw its own PML exceptions. The exception to throw is PMLNetException. For example
This may then be handled inside a PML macro i.e.
Any other exception within the loaded assembly itself is caught by the global exception handler inside the AVEVA module.
Certain rules must be adhered to when defining a .NET class which is PML callable. These are enforced by the PMLNetEngine when an assembly is imported. They are
If these rules are not adhered to then errors are reported to the trace log when the assembly is loaded and a PML class definition will not be created. If the class definition has not been defined then the following PML error will result
In order to output trace to a log file and the console window add the following lines to the exe's config file
This will create the file PMLNetTrace.log in C:\temp and log all the valid class definitions as they are imported.
 USING NAMESPACE ‘Aveva.Core’

 !netobj = object namespace.NETObject ( )
!a = object netobject()
USING NAMESPACE <string>
'Aveva.Core.PMLNetExample'
!netobj = object  NetObject ( )
 (46,87)   PML: Object definition for NETOBJECT could not be found.
 q  var !x

 < Aveva.Core.NAMESPACE.NETOBJECT>
Aveva.Core.NAMESPACE.NETOBJECT
 Q METH/ODS
q meth !x

<Aveva.Core.NAMESPACE.NETOBJECT>Aveva.Core.NAMESPACE.NETOBJECT
          NETOBJECT ( )
          NETOBJECT (REAL)
          ADD (REAL)
          REMOVE(REAL)
          ASSIGN(Aveva.Core.NAMESPACE.NETOBJECT)
          DOSOMETHING(REAL, REAL, REAL)
Q NAMESP/ACES
    .methods()
   !arr = !x.methods()
   q var !x
<ARRAY>
 [1] <STRING> 'NETOBJECT ( )'
 [2] <STRING> 'NETOBJECT (REAL)'
 [3] <STRING> 'ADD (REAL)'
 [4] <STRING> 'REMOVE(REAL)'
 [5] <STRING> 'ASSIGN(Aveva.Core.NAMESPACE.NETOBJECT)'
 [6] <STRING> 'DOSOMETHING(REAL, REAL, REAL)'
IMPORT <string>
!a = object netobject()
!a.val(1)
!b = !a
!b.val(2)
then
q var !a.val() returns 1
and
q var !b.val() returns 2
[PMLNetCallable()]
namespace PMLNet
{
    [PMLNetCallable ()]
    public class PMLNetExample
    {
        [PMLNetCallable ()]
        public PMLNetExample()
        {

        }
        [PMLNetCallable ()]
        public void DoSomething(double x, double y, double z)
        {
             z = x + y;
        }
    }
}
using Aveva.Core.PMLNet;

[assembly: PMLNetCallable()]
[PMLNetCallable()]
public double Val

{
   get
   {
      return mval;

   }
   set
   {

      mval = value;
   }

}
REAL VAL()
VAL(REAL)
__delegate void PMLNetEventHandler(ArrayList __gc *args);

[PMLNetCallable()]
public class PMLNetExample

{
[PMLNetCallable()]
public event PMLNetDelegate.PMLNetEventHandler PMLNetExampleEvent;

 [PMLNetCallable()]
 public PMLNetExample ()

 {
 }
 [PMLNetCallable()]
 public void Assign(PMLNetExample that)

 {
    }
 [PMLNetCallable()]
 public void RaiseExampleEvent()

 {
     ArrayList args = new ArrayList();

           args.Add("PMLNetExampleEvent ");
           args.Add("A");
           if (PMLNetExampleEvent!= null)
               PMLNetExampleEvent(args);

      }
}
!n = object pmlnetexample()
!c = object netcallback()
!handle = !n.addeventhandler('pmlnetexampleevent', !c, 'callback')
!n.removeeventhandler('pmlnetexampleevent', !handle)
define method .callback(!array is ARRAY)
 !args = 'NETCALLBACK object ' + !array[0] + !array[1]
 $P $!args
endmethod
throw new PMLNetException(1000, 1, "PMLNetExample Exception");

handle(1000,1)
…
endhandle
(46,87)   PML: Object definition for XXX could not be found.
<system.diagnostics>
       <switches>
          <add name="PMLNetTraceSwitch" value="4" />
       </switches>
  </system.diagnostics>
<appSettings>
        <add key="PMLNetTraceLog" value="C:\temp\PMLNetTrace.log" />
</appSettings>
Only .NET classes which are marked as PMLNetCallable and adhere to certain rules can be called from PML (these rules are described later)
Module switching does not persist .NET objects. Core PML objects defined in FORTRAN or C++ are not persisted either.
Passing other PML system/user objects to .NET, for example: DIRECTION, ORIENTATION, … is not possible. It is possible to pass database references to .NET either as an array or String. It is also possible to pass an existing instance of a PML.NET Proxy to .NET.
It is not possible to call directly PML objects from .NET. The only way to call PML from .NET is via events.
It is not possible to enter 'partial' namespaces as you might in C# and expect them to be concatenated.
Only .NET classes which are marked as PMLNetCallable and adhere to certain rules can be called from PML (these rules are described later)
Only .NET classes which are marked as PMLNetCallable and adhere to certain rules can be called from PML (these rules are described later)
Module switching does not persist .NET objects. Core PML objects defined in FORTRAN or C++ are not persisted either.
Module switching does not persist .NET objects. Core PML objects defined in FORTRAN or C++ are not persisted either.
Passing other PML system/user objects to .NET, for example: DIRECTION, ORIENTATION, … is not possible. It is possible to pass database references to .NET either as an array or String. It is also possible to pass an existing instance of a PML.NET Proxy to .NET.
Passing other PML system/user objects to .NET, for example: DIRECTION, ORIENTATION, … is not possible. It is possible to pass database references to .NET either as an array or String. It is also possible to pass an existing instance of a PML.NET Proxy to .NET.
It is not possible to call directly PML objects from .NET. The only way to call PML from .NET is via events.
It is not possible to call directly PML objects from .NET. The only way to call PML from .NET is via events.
It is not possible to enter 'partial' namespaces as you might in C# and expect them to be concatenated.
It is not possible to enter 'partial' namespaces as you might in C# and expect them to be concatenated.
!n is the PML.NET instance on which the event will be raised
!c is the instance of a PML object with a method callback() with the appropriate arguments
!n is the PML.NET instance on which the event will be raised
!n is the PML.NET instance on which the event will be raised
!c is the instance of a PML object with a method callback() with the appropriate arguments
!c is the instance of a PML object with a method callback() with the appropriate arguments
PML callable assemblies must be marked as PMLNetCallable and reside in the %AVEVA_DESIGN_EXE% directory, subdirectory of the application or UNC path.
Only classes may be PML Callable (this excludes Structures, Interfaces, Enums, …).
A PML callable class must be marked as PMLNetCallable.
A PML callable method must be marked as PMLNetCallable.
A PML callable method can only pass valid argument types (see table of types).
PML callable classes and methods must be public.
PML callable methods with default arguments cannot be defined.
PML callable class and method names must be case independent.
PML callable classes must have an Assign() method.
PML callable classes must have a public default constructor which is PMLNetCallable.
PML callable assemblies must be marked as PMLNetCallable and reside in the %AVEVA_DESIGN_EXE% directory, subdirectory of the application or UNC path.
PML callable assemblies must be marked as PMLNetCallable and reside in the %AVEVA_DESIGN_EXE% directory, subdirectory of the application or UNC path.
Only classes may be PML Callable (this excludes Structures, Interfaces, Enums, …).
Only classes may be PML Callable (this excludes Structures, Interfaces, Enums, …).
A PML callable class must be marked as PMLNetCallable.
A PML callable class must be marked as PMLNetCallable.
A PML callable method must be marked as PMLNetCallable.
A PML callable method must be marked as PMLNetCallable.
A PML callable method can only pass valid argument types (see table of types).
A PML callable method can only pass valid argument types (see table of types).
PML callable classes and methods must be public.
PML callable classes and methods must be public.
PML callable methods with default arguments cannot be defined.
PML callable methods with default arguments cannot be defined.
PML callable class and method names must be case independent.
PML callable class and method names must be case independent.
PML callable classes must have an Assign() method.
PML callable classes must have an Assign() method.
PML callable classes must have a public default constructor which is PMLNetCallable.
PML callable classes must have a public default constructor which is PMLNetCallable.
Note:
Query methods will not list the methods on objects of type ANY, even though such methods are available on all objects.

Note
:
do not
using
[PMLNetCallable()]
public double
   get
   {
      return
   set

value
;

ToString() Method
delegate void
__gc
public class
public event

public

public void

public void
= new

if
null
)

!n
!c
!handle
throw new