Registry Entries for Automation Objects

As for any object with a CLSID, an automation object requires a few basic registry entries to tell OLE where its server is located. It is also necessary to tell automation controllers where to find your type information given your CLSID. Knowing this, controllers don't have to instantiate an object of your class just to see what the object can do.

Three basic sets of entries for each automation object fall under the CLSID key, the TypeLib key, and your ProgID key or keys. These entries are necessary for each separate object CLSID, which is true for any other object server.

Under your CLSID entry, you should register the following:


\CLSID
{<CLSID>} = <name of object>
[Inproc œ Local]Server[32] = <path to DLL or EXE> [/Automation]
InprocHandler[32] = <handler path or OLE2.DLL/OLE32.DLL>
ProgID = ...
VersionIndependentProgID = ,,,
TypeLib = {<LIBID> spelled out as a CLSID}
Programmable

We've already seen the entries for type information in Chapter 3. Here NotInsertable keeps the object out of Insert Object dialog boxes in OLE Documents containers. If an object can be inserted as well as embedded, this will be Insertable. I suggest, as an extension to OLE Automation, the Programmable key to indicate that the object supports OLE Automation, in the same way that Insertable marks a compound document object and Control marks an OLE Control, as we'll see later. You won't find Programmable in any other documentation. I suggest it as a means of identifying object classes that can be driven through Automation. Without such a key, you cannot differentiate these objects from a regular COM component that doesn't support IDispatch. Programmable is useful for controllers that would like to display a list of only automation-capable objects, but it is not a standard part of OLE.

The only other part of these registry entries related specifically to Automation is the optional /Automation command-line flag. If you are registering an application object for automation using LocalServer[32], you will want to include this flag to tell your EXE that it is being launched in order to create the application object. You don't put this flag on any other LocalServer[32] entries for other objects, even with the same EXE name, because you'll use it to determine whether you must create and register a single-use class factory for the application object's CLSID. Because the object will usually be created as part of application startup, you don't want to register a class factory for that CLSID unless OLE is going to specifically use it right away (and thus exhaust its single use). Otherwise, some client might come along and try to instantiate your application object at some later time. If your class factory has not been used, it would be called at that time, but it could not create a new application.

Also note that your ProgID entry provides for a convenient mapping from a textual object name like "Beeper.Object" to a CLSID. This might or might not be useful to certain controllers. Visual Basic and its various derivatives allow the user to write a piece of Basic code to create an object as follows:


Dim X as Object
Set X = CreateObject("Beeper.Object")

When executing this code, Visual Basic goes to the registry and looks for a ProgID named "Beeper.Object" and then finds "CurVer". It then looks under that versioned ProgID to find the CLSID, and with that CLSID it can call CoCreateInstance(IID_IDispatch) to instantiate the automation object and obtain its IDispatch pointer.

When OLE first establishes remote connections through a dispinterface, it automatically creates entries for IDispatch under the Interface key. If you have a dual interface and want to provide your own standard marshaling support, you can create your own entries under Interface as well using the IID of IDispatch as the BaseInterface entry.