action.skip

COM Connector

Use the Host Integrator COM connector to create Visual Basic and C++ applications that integrate host data into web applications or client/server applications. This section describes the COM API methods and provides you with tips on how to build powerful and robust applications by taking advantage of the COM connector's features and options.

The COM connector is installed as a component selection during the basic Host Integrator install program.

Intended Audience This reference is meant for COM and C developers who are familiar with object-oriented development environments and who have a thorough knowledge of Visual Basic, C++, or ASP web programming with scripting languages like JScript or VBScript. In addition, you should become familiar with the Design Tool and Host Integrator Server and the model files associated with them. You can use Web Builder to create projects based on the demo models provided with Verastream Host Integrator and then examine the code in your projects to see how the connector works. To view examples of individual methods, see the Visual Basic methods help file.

Understanding the AppConn Object Model

The Host Integrator COM connector connects to the Host Integrator Server and implements four main interfaces. The AppConnSessionEx object implements these interfaces. Each of the following interfaces contains methods accessible from any programming environment that supports COM:

  • AppConnModel interface: Use model-level methods to access host data from the host application model. To use model level methods, you must have knowledge of the Design Tool's modeling process, though an intimate knowledge of the host application is not required.

  • AppConnChannel interface: The AppConn COM channel interface contains methods for connecting to and obtaining information about sessions and models running on Verastream Host Integrator Servers.

  • AppConnTable interface: Use table/procedure methods to access table definitions of data created during the Design Tool's modeling process and stored in the host application model. Using the methods in this interface requires no knowledge of the host application or the modeling process.

  • AppConnTerm interface: Use terminal methods to access data directly from the host. Unlike model-level methods, using terminal methods requires an intimate knowledge of the host application since the entity definitions created in the model file are not used with terminal level methods.

See the Accessing host data section of Using Host Integrator Connector APIs for more information on these interfaces.

Each of the main interfaces implements certain objects differently and may include additional objects derived from one of the basic objects. The following list describes each basic object and provides links to the corresponding sections of the Visual Basic Reference.

Each of the main interfaces implements certain objects differently and may include additional objects derived from one of the basic objects. The following list describes each basic object. See the Visual Basic Reference.

Object Description
AppConnRecord Provides storage for a collection of elements returned from the Host Integrator Server. It may also contain an index number and terminal attributes collection for data returned from the model interface (for example, FetchRecords and GetAttributes). Read-only
AppConnModelRecord A record that also implements index number and terminal attributes accessor functions using a derived class. The index number and terminal attributes collections are read-only.
AppConnRecordSet Provides storage for a collection of records and metadata for the elements of the records returned from the Host Integrator Server. Empty recordsets can be created and filled in by the FromXMLString method. Once you execute an insert on a recordset, you need to reset the recordset by either navigating away from it and returning, or executing the home operation on the recordset before executing any other method on it. Read-only.
AppConnStringList Provides dynamic storage for a list of strings that can be used to send data to, and retrieve data from, an AppConn session.
AppConnStringMap Provides dynamic storage for a keyed map of strings that can be used to send data to or retrieve data from, an AppConn session. You can also get data from a record.
AttributeMetaData Contains the metadata defined in the model for an entity attribute. This object is read only.
ColumnMetaData Contains the metadata defined in the model for a table column. Read-only.
FieldMetaData Contains the metadata defined in the model for a recordset field. Read-only.
OperationMetaData Contains the metadata defined in the model for a procedure. Read-only.
ProcedureMetaData Contains the metadata defined in the model for a procedure. Read-only
RecordSetMetaData Contains the metadata defined in the model for a recordset. Read-only.
TerminalAttributes Contains the screen attributes on the host terminal for an attribute or field. Read-only.
VariableMetaData Contains the metadata defined in the model for a model variable. Read-only
ElementLocationList Provides storage for a list of element locations. Read-only
TerminalField Contains the location information for the element. Read-only
StringMapSet Provides dynamic storage for a list of string maps that can be used to send data to an AppConn session.

Using AppConn COM from Visual Basic

To use AppConn in a Visual Basic project, select References from the Project menu and select AppConn from the list of available references. If AppConn does not appear, use the Browse button to select the appconn.dll from the Windows\System32 folder.

Once AppConn is included in the project, all of the AppConn objects will appear in the Visual Basic IntelliSense. If AppConnLib is selected when using the IntelliSense, a list of the AppConn objects will appear. Objects may be declared with or without the AppConnLib prefix. The following declarations are the same:

  Dim Session As AppConnTable
  Dim Session As AppConnLib.AppConnTable
  ```

To create an AppConn object, use the new operator: `Set Session = new AppConnTable`

Visual Basic IntelliSense provides a list of properties and methods available for the object. IntelliSense also provides a list of the parameters for methods. The IntelliSense also supplies the parameter type. Optional parameters are enclosed in square brackets (e.g. [varUserID] ).

IntelliSense will also show the return type for methods that have parameters. Variables can be set to object properties and method return values. If the property return type is a COM object, Visual Basic requires using Set; otherwise a simple assignment statement can be used.

```java
  Dim Rec As AppConnRecordSet
  Dim Index As Long
  Dim Connected As Boolean

  ' Requires Set because method returns a COM object
  Set Rec = Session.FetchRecords 

  ' Does not require Set because method returns a long
  Long Index = Session.GetCurrentRecordIndex  

  'Does not require Set because property is a Boolean 
  Connected = Session.IsConnected

Visual Basic requires that properties and methods that return a value use parentheses when parameters are included in the call.

 ' Does not require parentheses because all of the parameters are optional 
  ' and none are included
  Set Recs = Session. FetchRecords  

  ' Requires parentheses because a parameter is included
  Set Recs = Session. FetchRecords (1) 

  'Requires parentheses because parameters are included and a return value is used
  Set Recs = PerformTableProcedure("Pets",  "Get")

  ' Does not require parentheses because return value is not used
  PerformTableProcedure "Pets", "Delete"
  ```

 **Examples**

 You can use Web Builder to create projects based on the "demo" models provided with Host Integrator and then examine the code in your projects to see how the connector works. Examples for individual methods are included with the [Visual Basic Methods Reference](com-vb-method-reference.md).

 **Handling errors**

Errors can be handled by declaring on On Error handler. A handler can be either Resume Next, GoTo 0, or GoTo `<label>`.

Resume Next will ignore the error and continue executing the next statement: `On Error Resume Next`

GoTo 0 will use the default error handler:  `On Error GoTo 0`

GoTo `<label>` will cause the program to jump to the label and execute the next statement.

```java
 On Error GoTo HandleError
     Session.ConnectToModel "localhost", "CCSDemo"
  Exit Sub

  ErrorHandler:
     MsgBox Err.Description, vbOKOnly + vbCritical, "Error"
 ```

**Using Variable Type Parameters**

Visual Basic allows variable type parameters. For example, the Item method of the AppConnStringMap can take either a number (the index of an element) or a string (the key of an element). The method will determine the type of the parameter and return the correct element for that type.

```java
  Dim Attributes As AppConnStringMap
  Dim Attribute as String

  Set Attributes = new AppConnStringMap 'Create the string map
  Attributes.Add("LastName", "Culver") 'Populate the string map
  Attribute = Attributes.Item(1) 'Get the first element (VisualBasic indexes start at 1)
  Attribute = Attributes.Item("LastName") 'Get the element named "LastName"

Using Default Methods

Default methods can be defined for COM objects. When the method name is omitted Visual Basic will use the default method. For the AppConnRecordSet, AppConnRecord, AppConnModelRecord, AppConnStringList, and AppConnStringMap the Item method is defined as the default method. The calls to the Item method can be written as follows:

Attribute = Attributes(1)
Attribute = Attributes("LastName")

When the parameter is a string, the default method can be invoked using the exclamation point (!) and the parameter string without quotes: Attribute = Attributes!LastName

The AppConnRecordSet, AppConnRecord, AppConnModelRecord, AppConnStringList, and AppConnStringMap objects are defined as COM collections, which means that VisualBasic can iterate over the collection using the For Each Next construct. In the following example a For Each statement is imbedded inside a For Each statement to iterate over each record in a record set and each field in the record:

Dim Rec
  Dim Field
  Dim Line As String

  For Each Rec In Recs
     Line = "Fields:"
     For Each Field In Rec
        Line = Line + " " + Field
     Next
   Next

C++ with an Import Statement

To begin using AppConn in your C++ project, the AppConn COM control must be imported into the project using the VC++ compiler. To import the appConn.dll, installed to the \Winnt\System32 folder by default, place the following import statement at the beginning of the source file that will be using the AppConn component:

#import "appconn.dll"

The import command will generate two new files, appconn.tlh and appconn.tli, which are automatically included in the source file. The appconn.tlh file defines wrapper classes for each of the AppConn interfaces, smart pointers for the wrapper classes, and all of the AppConn constants inside of the namespace AppConnLib. To use the AppConn definitions, the AppConn definition must be prefaced with AppConnLib:: or by including a using namespace statement: using namespace AppConnLib;

Accessing AppConn Using the Smart Pointer and Wrapper Class

AppConn objects are accessed using the smart pointer to the wrapper class. The smart pointer will perform all of the life time management for the object. When an object is assigned to the smart pointer, the smart pointer will call AddRef on the object. When the pointer is reassigned, the smart pointer will call Release on the object, and when the smart pointer is destroyed it will call Release on the object. The smart pointer's name is the name of the interface with the suffix "Ptr". For example, declare an interface pointer with the following statement:

IAppConnTablePtr pTable;

To create an AppConn object, use the smart pointer CreateInstance method passing the class Id, which can be obtained using the __uuidof keyword with the class name. CreateInstance will return an HRESULT, which can be checked for success or failure.

hr = pSession.CreateInstance(__uuidof(AppConnTable));

The wrapper class creates a wrapper method for each object method. The methods do not return an HRESULT the way COM method normally do, but will throw the exception com_error if the call fails, so all calls should be placed inside a try/catch block. The _com_error exception contains the ErrorInfo for the error that occurred. Optional parameters which are declared as _variant_t have a default parameter, so they may be omitted. The wrapper class replaces BSTR parameters with the wrapper class _bstr_t and VARIANT parameters with the wrapper class _variant_t. _bstr_t contains a BSTR and will automatically convert from char , wchar_t, BSTR, and _variant_t. _bstr will call SysAllocString to create the internal string, and will call SysFreeString to destroy the string when a new value is assigned or when it is destroyed. _variant_t contains a VARIANT and will automatically convert values that can be stored as a VARIANT. _variant_t will call VariantClear to destroy the variant when a new value is assigned or when it is destroyed. By changing BSTR and VARIANT to the wrapper classes, parameters can be passed to the method as primitive COM pointer or printf type and the compiler will handle conversion and life type management. Methods will return the COM return value directly instead of as the last parameter of the parameter list as COM methods normally do.

  try {
     pSession->ConnectToModel("localhost","CCSDemo","bjones","bjones");
  }
  catch (_com_error &err) {
     printf("Error: %s\n", OLE2A((LPOLESTR) err.Description()));
  }

Return values from the wrapper class method are returned directly to the caller. BSTR values are returned as _bstr_t, VARIANT values are returned as _variant_t, and pointers to COM interfaces are returned as smart pointers, so life management will be handled automatically by the returning object.

  _bstr_t bstrString;
  try {
     bstrString = pSession->GetStringAtOffset(10, 5);
  }
  catch (_com_error &err) {
     printf("Error: %s\n", OLE2A((LPOLESTR) err.Description()));
  }

The wrapper class also declares properties which the compiler treats as data members by changing their references into function calls. The properties can be treated like data members.

VARIANT_BOOL bConnect = pSession->IsConnected

The wrapper class also declares properties with parameters. In the following example, Item is a property of AppConnStringMap which handles both get and put with an index that can be either a string or an number. Put with a string will add the key/value if the key does not exist and replace the value if the key does exist. Put with a number will replace the value if the index exists and throw an error if it does not.

IAppConnStringMapPtr pAttributes;

pAttributes.CreateInstance(__uuidof(AppConnStringMap));
pAttributes->Item["LastName"] = "S";
bstrt bstrLastName = pAttributes->Item[1];

The following example demonstrates the different ways the wrapper classes can be used to simplify using the AppConn objects. The first line inside the try block creates an instance of AppConnStringList assigned to pSelectFields. Because pSelectFields is declared as a smart pointer life time management will be done automatically and the object will be destroyed when pSelectFields goes out of scope. The second line inside the try block adds an entry to pFilter with the key "LastName" and value "Brown". Because the parameters to Add are declared as _bstr_t in the wrapper class the parameters will automatically be converted from char * to BSTR and cleaned up. The third line inside the try block executes the PerformTableProcedure method which will return an AppConnRecordSet. The value is assigned to pRecords which is a smart pointer.

If the return value is not assigned to a variable the AppConnRecordSet will be destroyed automatically. The first two parameters of PerformTableProcedure are declared as _bstr_t, so AppConn will automatically convert the parameters from char * to BSTR and clean up the values after the method call. The next five parameters are optional so they could be omitted and are declared as _variant_t in the wrapper class. The fourth parameter is included in the method call, so all the parameters up to the fourth parameter must be included.

The third parameter is declared inline as an instance of _variant_t, which will create an empty parameter and be handled as if it is omitted. The fourth parameter is passed as a smart pointer which _variant_t will automatically convert to a VARIANT and clean up the value when it is done. The for loop will iterate over each of the records in the recordset using the Count property declared in the AppConnRecordSet wrapper class to get number of records. The Item property declared in the AppConnRecordSet is used to assign each record to pRecord. The Detach method must be called on the smart pointer before assigning a value to pRecord; otherwise, it will cause an assert.

IAppConnRecordSetPtr pRecords;
 IAppConnStringMapPtr pFilter;
 IAppConnModelRecordPtr pRecord;
 try {
     pFilter.CreateInstance(__uuidof(AppConnStringMap));
     pFilter ->Add("LastName", "Brown");
     pRecords = pSession->PerformTableProcedure("Person", "GetPerson", 
     _variant_t(), pFilter);
     for (long i = 0; i < pRecords->Count; i++) {
         pRecord = pRecords->Item[i];
         pRecord.Detach();
        }
  }
  catch (_com_error &err) {
      printf("Error: %s\n", OLE2A((LPOLESTR) err.Description()));
  }

C++ without an Import Statement

Using AppConn COM from C++ without using the import statement provides an efficient way to use the AppConn COM connector without having to use the VC++ compiler. The following topics explain how to begin a C++ project without using an import statement.

Overview

The following files contain the definitions needed to create and use the AppConn controls: appconn_i.c and appconn.h (located in the <VHI install folder>\include folder). The appconn_i.c file contains the AppConn class and interface Ids. This file should be compiled and linked with the program that uses AppConn. The appconn.h file contains the interface definitions for all of the AppConn objects, all of the AppConn constants, and external references to the AppConn class and interface Ids defined in appconn_i.c. This file should be included in source files that use AppConn objects using the following statement:

#include "appconn.h"

AppConn objects are accessed using an interface pointer to the object. To declare an interface pointer, use the following statement:

IAppConnModel *pSession;

Creating an AppConn Object

To create an AppConn object, use the CoCreateInstance method, passing the class Id, the aggregate object's IUnknown interface, the class context, the interface Id, and a pointer to the interface pointer. CoCreateInstance will return an HRESULT, which can be checked for success or failure.

HRESULT hr = CoCreateInstance(CLSID_AppConnModel,
     NULL, 
     CLSCTX_INPROC_SERVER, 
     IID_IAppConnModel, 
     (LPVOID *)&pSession);

Object lifetimes must be managed explicitly. When an object is assigned to another interface pointer AddRef must be called on the interface, and when the interface is no longer used Release must be called. When the reference count goes to 0 the object will be deleted.

IAppConnModel *pModel = pSession;
pModel->AddRef();
pSession->Release();
pSession = NULL;

Converting C++ Types Into COM Types

Calling AppConn methods may require converting C or C++ types into COM types. Strings must be converted to BSTR using SysAllocString to create the string and SysFreeString to destroy it. bool must be converted to VARIANT_BOOL and set to either VARIANT_FALSE (0) or VARAINT_TRUE (-1). Variant parameters must be initialized using VariantInit and destroyed using VariantClear. Optional parameters are declared as VARIANT and may be set as VT_EMPTY or VT_NULL to indicate that the parameter is not being included. Return parameters are returned to the caller as a pointer to an object in the last parameter of the method. All methods return an HRESULT.

BSTR bstrServer;
  BSTR bstrModel;
  VARIANT varUserID;
  VARIANT varPassword;
  VARIANT varModelVariables;

  bstrServer = SysAllocString(L"localhost");
  bstrModel = SysAllocString(L"CCSDemo");
  VariantInit(&varUserID); //Will set VARIANT to VT_EMPTY
  VariantInit(&varPassword); //Will set VARIANT to VT_EMPTY
  VariantInit(&varModelVariables); //Will set VARIANT to VT_EMPTY
  hr = pSession->ConnectToModel(
     bstrServer,
     bstrModel,
     varUserID,
     varPassword,
     varModelVariables);
     SysFreeString(bstrServer);
     SysFreeString(bstrModel);
     VariantClear(&varUserID);
     VariantClear(&varPassword);
     VariantClear(&varModelVariables
 );
 ```
When a method call fails, the HRESULT may contain a standard Windows error code or a custom AppConn error code. The AppConn error codes are as follows: 

```java
APPTRIEVE_ERROR = 0x801E0001;
CHANNEL_ERROR = 0x801E0002;
SERVER_ERROR = 0x801E0003;
MARSHALLER_ERROR = 0x801E0004;
TIMEOUT_ERROR = 0x801E0005;
MODEL_DATA_ERROR = 0x801E0006;
MODEL_DEF_ERROR = 0x801E0007;
TERMINAL_ERROR = 0x801E0008;
DEAD_SESSION_ERROR = 0x801E0009;
USER_EXCEPTION_ERROR = 0x801E000A;
LOCKING_ERROR = 0x801E000B;
ALREADY_CONNECTED_ERROR = 0x801E000C;
NOT_CONNECTED_ERROR = 0x801E000D;
INVALID_ARG_ERROR = 0x801E000E;
INVALID_POINTER_ERROR = 0x801E000F;
BAD_VAR_TYPE_ERROR = 0x801E0010;
OUT_OF_MEMORY_ERROR = 0x801E0011;
ELEMENT_DOES_NOT_EXIST_ERROR = 0x801E0012;
ELEMENT_ALREADY_EXISTS_ERROR = 0x801E0013;
UNKNOWN_ERROR = 0x801E0014;

Error Handling

To get more specific error information, retrieve the ErrorInfo object. The ErrorInfo object is a standard COM object that can be retrieved by calling GetErrorInfo. ErrorInfo is stored in thread local storage, so there can only be one ErrorInfo object. AppConn will set the ErrorInfo when an error occurs and clear the ErrorInfo on the next call to an AppConn object. The ErrorInfo object contains a textual description of the error that can be accessed with the GetDescription method.

  IErrorInfo *pErrorInfo;
  LPOLESTR strDescription;
  if (SUCCEEDED(GetErrorInfo(0, &pErrorInfo)))
  {
      pErrorInfo->GetDescription(&strDescription);
      printf("Error: %s\n", OLE2A((LPOLESTR) strDescription));
      SysFreeString(strDescription);
      pErrorInfo->Release();
  }

Using ASP with VBScript

VBScript works the same as Visual Basic except for some notable exceptions:

  1. Types cannot be declared in VBScript with the As keyword.
  2. Objects are not created with the new operator, but with CreateObject method.
Set Session = Server.CreateObject ("VeraStream.AppConnTable") 'Create an instance in ASP

Set Session = Wscript.CreateObject ("VeraStream.AppConnTable") 'Create an instance in vbs engine

Error Handling

On Error Goto Label does not work in VBScript, so error handling is done inline by checking the Err object:

Session.ConnectToModel "localhost", "CCSDemo"
 If Err.Number <> 0 Then
      'Perform error handling
End If