Introduction
The building blocks of the Industrial Application Server are Application Objects. These objects themselves are made out of components called Primitives. Primitives have Attributes and Attributes have Properties. Each Application Object has at least the Common Primitive that is shared amongst all objects. In addition to this Primitive Application Objects can contain several other Primitives that are provided by the Industrial Application Server. On top of the basic set of Primitives one or more Custom Primitives can be added to an Application Objects. The Application Object Toolkit provides the tools to create Custom Primitives and glue them together with other standard Primitives to create a new type of Application Object.
Figure 1: Components of the International Spacestation
The AOT allows a developer to statically define Attributes of a new Custom Primitive in the Object Designer, or to dynamically create Attributes in the PackageServer component of the new Application Object. This post explains how to create Dynamic Attributes to expose other Attributes that are for example only available during configuration to the runtime sub system.
Prerequisites
The sample Application Object discussed in this post has been developed using the following tools:
- Visual Studio.NET 2003
- IAS 3.0 SP1
- Application Object Toolkit 1.0
Problem description
Some Attributes values are only available during the configuration of the object and are not accessible at runtime. The Attributes "MinorVersion" and "CodeBase", which are part of the Common Primitive, are configuration only Attributes. The following sample describes a simple approach to exposing these values to the runtime sub system by creating new Dynamic Attributes that are visble in runtime and copying the values of the configuration Attributes into the new Dynamic attributes
Figure 2: MinorVersion and CodeBase Attributes are ConfigOnly
Solution
Create new AOT project
Open the AOT Object Designer and create a new object called "ExportPackageOnlyAttributes". Then add one static Attribute in the Designer of type integer with the name "PV". Assign it the category "Writeable_USC_Lockable"
Figure 3: Creating a new object with the Object Designer
Now generate the source code, open the Visual Studio solution and build the new Application Object. Import it into the IDE and deploy it to an Application Engine.
Modify the Package Server
From this point on all modifications are made to the "ExportPackageOnlyAttributesPackage.cpp" file of the Package Server Visual Studio project. The code that we are going to add will be executed by the "CExportPackageOnlyAttributesPackage::OnPostCreate" event handler.
Add Attribute
To add a new attribute we need access to two functions that are provided by the Site COM object, which we get by calling the GetSite() function. First we want to make sure that the Attribute hasn't already been added by checking "GetAttributeHandle" passing in the name of our Dynamic Attribute. If it returns a valid handle, then we know that the Attribute has already been added, if not we are going to add the Attribute.
1: // Create two dynamic attributes if they don't exist already
2: // First check whether they exist
3:
4: ATL::CComBSTR MinorVersionExName = L"MinorVersionEx";
5: ATL::CComBSTR MajorVersionExName = L"MajorVersionEx";
6: AttributeHandle MinorVersionExAttributeID;
7: AttributeHandle MajorVersionExAttributeID;
8:
9:
10: IPrimitivePackageSite * P = GetSite();
11:
12: // 1) MINOR VERSION
13: HRESULT r = P->GetAttributeHandle( MinorVersionExName, &MinorVersionExAttributeID);
14:
15: if(!(SUCCEEDED(r)))
16: { 17: LogWarning(L"GetAttributeHandle - HRESULT = %x", r);
18: return;
19: }
20:
21: LogInfo(L"%s has AttributeID = %d" , MinorVersionExName, MinorVersionExAttributeID.shAttributeId);
22:
23: // If Attribute doesn't exist, create one
24: if( MinorVersionExAttributeID.shAttributeId == 0)
25: { 26:
27: AttributeInfo ai;
28: AttributeID ID;
29:
30: ai.Name = MinorVersionExName;
31: ai.Category = MxCategoryWriteable_C_Lockable;
32: ai.Security = MxSecurityFreeAccess;
33: ai.Datatype = MxInteger;
34: ai.LockType = MxLockedInMe;
35:
36: //Add dynamic attribute
37: r = P->AddAttribute(eTopLevelCustomPrimitiveId, &ai, &ID);
38:
39: if(!(SUCCEEDED(r)))
40: { 41: LogWarning(L"AddAttribute - HRESULT = %x", r);
42: return;
43: }
44:
45: LogInfo(L"Added Attribute %s! Its AttributeID = %d" , MinorVersionExName, MinorVersionExAttributeID.shAttributeId);
The category of the two Dynamic Attributes is set "Writeable_C_Locable". This way the Attribute values are constants and cannot be changed in runtime.
Set Value
Once we created the new Dynamic Attributes we can get the values from the "MinorVersion" and "CodeBase" and copy them to the new Dynamic Attributes "MinorVersionEx" and "MajorVersionEx". For the latter one we have to parse the "CodeBase" Attribute value string and get the version number at the end of the string. Here is the source code that does it.
1: // Set value of dynamic attribute equal to PackageOnly MajorVersion attribute
2: CMxValue MxCodeBase = Get(idxCommonCodeBase, eCommonPrimitiveId);
3: long int MajorVersion = 0;
4: ATL::CComBSTR CodeBase = L"";
5:
6: // Getting CodeBase attribute from Common Primitive
7: r = MxCodeBase->GetString(&CodeBase);
8: if(!(SUCCEEDED(r)))
9: { 10: LogWarning(L"GetString - HRESULT = %x", r);
11: return;
12: }
13: LogInfo(L"CodeBase is: %s", CodeBase);
14:
15: // Converting BSTR to STL wstring
16: std::wstring strCodeBase(CodeBase);
17:
18: // Parsing version number from ProgID string contained in CodeBase attribute
19: size_t b = strCodeBase.find_last_of(L".");
20: LogInfo(L"b %d", (int) b);
21: std::wstring strMajorVersion = L"";
22: strMajorVersion = strCodeBase.substr(b + 1);
23:
24: // Converting string to long integer
25: swscanf(strMajorVersion.c_str(), L"%d", &MajorVersion);
26:
27: LogInfo(L"MajorVersion String: %s", strMajorVersion.c_str());
28: LogInfo(L"MajorVersion Integer: %d", MajorVersion);
29:
30: // Converting long integer to MxValue object
31: CMxValue MxMajorVersion(MajorVersion);
32:
33: // Setting MajorVersionEx attribute value
34: Set(ID, MxMajorVersion);
Build and test
Compile the modified project, import the new object and deploy it. The new dynamic attributes should now display the values of the configuration counter parts. Check the object property page in the IDE and the runtime values of object attributes in the ObjectViewer.

Figure 4: Object properties displayed by the IDE
Figure 5: ObjectViewer displays the new Dynamic Attributes
Download
The complete Visual Studio .NET 2003 solution can be downloaded here: CExportPackageOnlyAttributes.zip
Summary
Creating Dynamic Attributes is without any doubt an advanced feature of the Application Object toolkit. On the other hand Dynamic Attributes can increase productivity of an application developer by providing a mechanism to automate the "shaping" of an Application Object.