ActiveX and TestStand
Overview
ActiveX and the technologies from which it is derived (COM and OLE) is very complex and fills many volumes of textbooks.
The following is a brief summary of ActiveX and of TestStand's implementation as an ActiveX Server application.
Table of Contents
ActiveX Defined
ActiveX is the general name for a set of Microsoft technologies that allows users to reuse code and link individual programs together to suit their computing needs. Based on Component Object Model (COM) technologies, ActiveX was originally developed as an extension of a previous technology called Object Linking and Embedding (OLE) in order to facilitate the development requirements of internet-based applications. OLE applications now fall under the umbrella of ActiveX.The guiding principle behind these technologies is to maximize the reuse of software components. ActiveX has developed a standard software interface which allows software vendors to develop applications which any application that supports the ActiveX standard can use. For example, a LabVIEW or LabWindows/CVI user could develop an application which reads or writes information to/from an Excel spreadsheet. LabVIEW, LabWindows/CVI, and Excel all support the ActiveX standard. In fact, using ActiveX a user could develop an application which uses components from all three of these applications.
ActiveX Automation
ActiveX Automation refers to the process of controlling one program from another via ActiveX. Much like networking, one program acts as the client and the other acts as the server. TestStand supports automation as the server. Both programs (client and server) exist independent of each other, but they are able to share information. To share information, the automation client communicates with ActiveX objects that the automation server exposes. The objects have properties and methods that can be accessed from the automation client. Properties are simply attributes of an object whose values can be set or retrieved from other programs. Similarly, methods are functions that are performed on objects, and they can be invoked from other programs. For example, a server might expose an object called Page. Properties of the Page object might be height, width, text size, and content. Methods of the Page object might be Save, Print, or Format.
An ActiveX server is any executable code available to other applications according to the ActiveX standard. ActiveX implies a client/server relationship in which the client requests objects from the server and the server performs actions on the objects.
Clients and servers can run on a single computer or they can run on separate computers connected by a network. An ActiveX server is called local when it runs on the same computer as its client and remote when it runs on a different computer.
On a single computer, an ActiveX server runs either in-process or out-of-process with respect to the client. An in-process ActiveX server is a dynamic-link library (DLL) that runs in the same process space as the client. An out-of-process ActiveX server is an executable and thus does not run in the same process space as the client. Using an out-of-process server instead of an in-process server can add significant performance overhead to the client application.
ActiveX Interface
The interface for an ActiveX server consists of the following hierarchical, object-oriented categories.
Object -- An object is a service that an ActiveX server makes available to clients.
Class -- A class is like a data type definition except that it applies to objects rather than variables. A class defines a list of methods and properties that you can use with respect to the objects that you create as instances of that class. For some classes, you can create objects directly. For other classes, you can obtain objects only by calling a method or property on an already existing object of another class.
Method -- A method performs an operation or function on an object.
Property -- A property stores and maintains a setting or attribute of an object.
ActiveX Controls and Containers
ActiveX controls are embedded components that exist inside ActiveX containers. TestStand does not function as an ActiveX container. Any program that can function as an ActiveX container allows users to “drop” ActiveX controls into the program. When a program is an ActiveX container, the ActiveX controls you drop into the program have their own functionality and properties which you can manipulate via properties and methods.
ActiveX Events
ActiveX is an event-driven technology. This means that programs report when certain events occur so that other programs or the user can react accordingly. In TestStand, the UIMessage Class Object is the primary event interface. An event interface provides communication from the server back to the client. The client supplies the server with a pointer to the interface. When the server notifies a client that an event occurred, the server calls methods in the event interface and the client’s code is executed.
In TestStand, you use the UIMessage Class Object event interface within a customized operator interface to receive events from the TestStand engine. The engine notifies you of the execution state by sending you messages such as Start, End, Break, and Trace. You can update your application's user interface in response to these messages. There are other methods of receiving messages from the TestStand engine if your application development environment does not support handling of ActiveX events.
ActiveX Advanced Issues
Object References
All ActiveX objects maintain reference counts. In other words, each object keeps track of the number of things that reference it. This allows the object to decide when to free the resources it uses. In most cases, test developers do not have to take any specific action to maintain this count. Nevertheless, you have to help maintain the reference count if you call a method or property that returns an object or if you store a pointer to an object in a global variable for use after your test module completes.
Adding and Releasing References
Whenever you create an ActiveX object directly or receive an ActiveX object as a return value from a method or property, you have a reference to the object. You must release this reference when you no longer require the object.
Normally, when you receive an object as a parameter to a function or LabVIEW VI, you do not have to add or release a reference to the object. This is because the caller of the function already holds a reference to the object. If, however, the function or VI stores the object to use after the function or VI returns, you must add a reference to the object in the function or VI. You must release the reference when you no longer require the object.
In general, maintaining a reference to an object guarantees its existence for at least at long as you hold that reference. The object frees its resources only when you release the final reference to the object.
The following sections explain how to add and release references to objects from each language.
LabVIEW
No cases currently exist in LabVIEW where you have to add a reference to an ActiveX object.
To release a reference to an ActiveX object in LabVIEW, wire the reference to the ActiveX Automation Close function.
LabWindows/CVI
To add a reference to an object in LabWindows/CVI, you must use functions from the ActiveX Automation Library as follows:
LPDISPATCH tmpDispatchPtr;
CAObjHandle newObjReferenceHandle;
CA_GetDispatchFromObjHandle(objHandle, &tmpDispatchPtr);
CA_CreateObjHandleFromIDispatch(tmpDispatchPtr, 1, &newObjReferenceHandle);
To release an object reference in LabWindows/CVI, you must use the following function from the ActiveX Automation Library.
CA_DiscardObjHandle(newObjReferenceHandle);
Visual Basic
Visual Basic automatically adds object references when you assign the object to another variable as in the following code:
Set newObjReference = objReference
Visual Basic also automatically releases object references when a variable or list that contains a reference to an object goes out of scope. Local variable scope ends when the function containing it returns. Static and global variable scope ends when you unload the module, form, or class object that contains the variable. You can force the release of a reference to an object by setting the variable to the value Nothing, as in the following code:
Set objReference = Nothing
MFC/C++
By default, if you attach a dispatch pointer to a TestStand MFC wrapper class object, the class releases a reference to the dispatch pointer when it destroys the object. This behavior, however, is not always what you want. For example, when you receive a dispatch pointer as a parameter, you must not release the reference to it. Releasing the reference can cause a fatal application error. To get around this, the AttachDispatch methods of the TestStand MFC wrapper classes has an optional second parameter to specify whether or not to auto-release the dispatch pointer. Pass FALSE to prevent the automatic release, as shown below:
int MyTestFunction (LPDISPATCH sequenceContextDisp)
{
SequenceContext context;
context.AttachDispatch(sequenceContextDisp, FALSE);
}
To add a reference to a dispatch pointer that a TestStand object uses, do the following:
object.m_lpDispatch->AddRef();
To explicitly release a reference to a dispatch pointer that a TestStand object uses, call the ReleaseDispatch method of the particular class.
All classes in the TestStand MFC interface derive from the MFC COleDispatchDriver class. For more information on the COleDispatchDriver class, refer to the MFC documentation for your compiler.
Visual C++/#import
The pointer classes generated by the #import directive automatically add object references when you construct a pointer as in the following code:
TS::PropertyObjectPtr newObjectPtr(objectPtr);
The assignment operator of the pointer classes first releases the reference to the object that it currently holds and then adds a reference to the object that is being assigned to it. For example, the following assignment statement first releases the reference to the object that newObjectPtr refers to and then adds a reference to the object that objectPtr refers.
newObjectPtr = objectPtr;
The destructor for the pointer class releases the object reference. Assigning the value NULL to a pointer variable releases the object reference, as shown below.
objectPtr = NULL; // releases the reference
Thread Concurrency Models
In ActiveX, there are two main concurrency models for which you can initialize a thread, apartment-threaded and multithreaded. Before you use a thread with ActiveX, you must initialize it to one of these models. In most cases, the software development environment you are using initializes the threads in your application for you.
When using the TestStand API to implement an operator interface or other application program, you may use threads of either concurrency model.
When using ActiveX from within a test module, you do not have to initialize the thread's concurrency model because TestStand initializes all execution threads as multithreaded for you.
Related Links:
A Brief Overview of ActiveX/COM
ActiveX and COM -- Part I
ActiveX and COM -- Part II
Reader Comments | Submit a comment »
Legal
This tutorial (this "tutorial") was developed by National Instruments ("NI"). Although technical support of this tutorial may be made available by National Instruments, the content in this tutorial may not be completely tested and verified, and NI does not guarantee its quality in any way or that NI will continue to support this content with each new revision of related products and drivers. THIS TUTORIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND AND SUBJECT TO CERTAIN RESTRICTIONS AS MORE SPECIFICALLY SET FORTH IN NI.COM'S TERMS OF USE (http://ni.com/legal/termsofuse/unitedstates/us/).
