This chapter explains the registration of COM objects so that they can function as COM Automation servers.
A COM Object must be registered with the Windows system before it can function as a COM Automation server and receive messages from a client. There are four ways of registering OO COBOL Automation servers:
All OO COBOL Automation servers register themselves automatically when run. This only works for out-of-process servers which can be run standalone. The information entered into the registry is minimal when you use this method.
This registers the server permanently. This requires some extra code in the server .dll which is created automatically by the Class Wizard. The COM objects created by the Interface Mapper must be registered using this method. See the section Enabling Self-registration for more information.
This registers the server permanently on the system.
The first of these methods can be very useful when you are developing and debugging a server. The other methods are preferable when you don't know when clients are likely to request the server to start. Once the server is entered into the Registry, Windows starts the server automatically when a client requests a new instance of the server.
Some development environments (for example Visual Basic) automatically register any new COM object you create on the development machine - although you don't see the registration being carried out, it still happens behind the scenes. You need to register the object on each machine where you want to deploy it.
The Net Express Class Wizard generates a .reg file with all the information you need to register an object, whenever you use it to create a COM Automation server. This is an ASCII text file containing the entries to be inserted into the Windows registry. The format of this file is documented in the section Editing Registry Entries.
The information enables a client to obtain a unique ID for the object (its Clsid) from the object's ProgID. The ProgID for OO COBOL classes is by default the filename of the class, although you can change this by editing method "queryClassInfo" (see the next section). The Clsid enables the client to find another entry in the registry which provides the information needed to start the COM Automation server.
There are two ways of entering the information in the .reg file into the Windows registry. Do one of the following:
regedit filename.reg You can build your COM Automation servers to contain all the information needed for successful registration. The information is stored inside two methods in each COM Automation class:
Returns information about the class.
Returns information about the class type library.
These methods are generated for you by the Class Wizard when you create a COM Automation class ("queryLibraryInfo" is only included if you generate a type library at the same time). You can change some of the information returned by these methods to alter self-registration details for your class.
The "queryClassInfo" method looks like this:
method-id. queryClassInfo.
linkage section.
01 theProgId pic x(256).
01 theClassId pic x(39).
01 theInterfceId pic x(39).
01 theVersion pic x(4) comp-5.
01 theDescription pic x(256).
01 theThreadingModel pic x(20).
procedure division using by reference theProgId
by reference theClassId
by reference theInterfceId
by reference theVersion
by reference theDescription
by reference theThreadModel.
move z"{clsid}" to theClassId
move z"{clsid}" to theInterfceId
move z"A description of your class" to theDescription
*> For automatic registration of the DLL, you can specify the
*> the ThreadingModel registry entry
move z"Apartment" to theThreadModel
exit method.
end method queryClassInfo.
where {clsid} is a string representing a 128-bit clsid. For example: {F08FCA68-286C-11D2-831F-B01A09C10000}. Do not alter the clsid value; it is generated by a Windows API call that guarantees every class a unique clsid. The clsid is used in a number of different places as part of registering a class and its interfaces and the values must match or the results are unpredictable. You can change the ProgID of the class by moving a null-terminated string with the new ProgID into data item theProgId. The version number is currently ignored by the COBOL run-time system.
The "queryLibraryInfo" method looks like this:
method-id. queryLibraryInfo.
linkage section.
01 theLibraryName pic x(512).
01 theMajorVersion pic x(4) comp-5.
01 theMinorVersion pic x(4) comp-5.
01 theLibraryId pic x(39).
01 theLocale pic x(4) comp-5.
procedure division using by reference theLibraryName
by reference theMajorVersion
by reference theMinorVersion
by reference theLibraryId
by reference theLocale.
*> currently ignored
move 1 to theMajorVersion
move 0 to theMinorVersion
move z"{clsid}" to theLibraryId
exit method.
end method queryLibraryInfo.
As for "queryClassInfo", you should not change the value of the library id. However, you can specify the location of the type library for a class by setting theTypeLibrary to one of the following:
| no string | Indicates that the type library is embedded as a resource in the .dll or .exe file for the class. This is the default location for classes created with the Class Wizard. |
| n | A numeric value indicates that the type library is a resource in the .dll or .exe file for the class. |
| path | A full path and filename to the type library. |
You can also optionally set major and minor version numbers for your type library by setting the values of theMajorVersion and theMinorVersion.
Registration procedures for in-process and out-of-process servers are described in the following two sections.
It is good practice to enable your out-of-process servers to register and unregister themselves. Self-registration is usually controlled by a command-line switch. See the Help topic To register an out-of-process COM object using the executable file for more information.
The olesup class has two methods, "registerServer" and "unRegisterServer" to enable you to do this easily. You need to add code to the trigger program for the server which detects switches on the command-line for registration and unregistration.
When the trigger program detects the registration switch, execute the following code:
invoke olesup "registerServer" using theClass commandline returning error-code
The "registerServer" method in olesup interrogates theClass for class and type library information using the "queryClassInfo" and "queryLibraryInfo" methods.
When the trigger program detects the unregistration switch, execute the following code:
invoke olesup "unregisterServer" using theClass returning error-code
where:
| Data Item | Datatype | Description |
|---|---|---|
| theClass | OBJECT REFERENCE | The class for registration. |
| commandline | PIC X(256) | The command-line to start the server. You should include the path to the server. |
| error-code | PIC X(4) COMP-5 | Returns 0 for a successful registration. If unsuccessful returns an OLE error code. |
The Microsoft regsvr32 utility enables you to register or unregister an in-process server (built as a .dll file) from the command line. See the Help topic To register an in-process COM object for more information.
In addition to the "queryClassInfo" and "queryLibraryInfo" methods generated automatically by the Class Library Wizard, the .dll file must include an entry-point named DllOleLoadClasses for regsvr32 registration to work. The Class Library Wizard also creates this automatically if you select the option to generate a trigger program for the class.
The code below shows an example of DllOleLoadClasses:
*> COM server trigger (for in-process servers only)
*> WARNING: Do not add further entry points to this file
$set case
linkage section.
01 loadReason pic x(4) comp-5.
procedure division.
entry "DllOleLoadClasses" using by value loadReason.
*> OCWIZARD - start classes
*> Calling the class registers it as available to OLE clients
call "myserver"
*> OCWIZARD - end classes
exit program.
.
The example above registers a single class called with the filename myserver.
You can add your own code to the DllOleLoadClasses - the parameter loadReason tells you why the COBOL run-time system has called this entry-point:
| 1 | Server is being loaded |
| 2 | Class is being registered |
| 3 | Server is being unregistered |
Net Express generates .reg files for you to make it easy to register your COM objects. This section provides some information on the format of these files, in case you need to change the path to a server. A .reg file is an ASCII file in the following format:
REGEDIT
[HKEY_CLASSES_ROOT\classname] @ = description [HKEY_CLASSES_ROOT\classname\Clsid] @ = uuid [HKEY_CLASSES_ROOT\CLSID\uuid] @ = description [HKEY_CLASSES_ROOT\CLSID\uuid\ProgID] @ = classname [HKEY_CLASSES_ROOT\CLSID\uuid\servertype] @ = startup
where:
The UUIDGEN tool is part of the Microsoft Platform SDK. Each time UUIDGEN runs, it generates a unique hexadecimal number.
To enter the information into the Windows registry, enter the following at a command prompt:
regedit registryfile
where registryfile is the name of the file with your registry entry.
You need to register the Automation server each time you install it into a different Windows system. You can use the same registry file each time - although if the registry file contains any machine-specific paths you must edit them.
Note: Registry files can vary in format and structure. For full details, see your Microsoft Platform SDK documentation.
You only need to read this section if you intend to build and run your servers multi-threaded. By default, OO COBOL servers are built single-threaded. Single-threaded COBOL programs cannot be run with any COM threading option other than single-threaded.
For more information about building multi-threaded programs with Net Express, from the Net Express toolbar, click Help > Help Topics. Then, on the Contents tab, click Programming > Multi-threaded Programming.
COM has the following different threading options for servers:
COM manages threading differently for out-of-process servers and in-process servers.
Out-of-process servers run as single-threaded when built for single-threading (the default for COBOL programs), and free-threaded when built for multi-threading.
To set a multi-threaded out-of-process server to run as apartment threaded, include the following statement in the trigger code for the server, before the class is executed:
invoke olesup "singleThread" returning aBoolean
where aBoolean is a PIC X(4) COMP-5, set to 1 for success.
The Net Express Class Wizard and Interface Mapper generate in-process servers using the multi-threaded "apartment" model by default. You can only change the threading options for in-process servers generated by the Class Wizard by editing its registry entry:
The full registry path to this key is: [HKEY_CLASSES_ROOT\{clsid}\InProcServer32] where clsid is the CLSID for the server.
Note: The registry files generated by Net Express do not include the named value ThreadingModel. It is not included in registry entries generated by running regsvr32 either.
You can either add this key to a registry file generated by Net Express, manually edit the registry file, or write code to use the Windows API to edit the registry when the server is registered. You can add this code to the entry-point DllLoadClasses in the in-process trigger program generated by the Class Wizard - see the section In-process Servers for more information.
By default, out-of-process servers terminate automatically when the last client logs out. This is not always desirable behavior if, for example, the server is displaying a window on the desktop. You can change this by using the "setOLETerminateOption" method in class OLESup:
invoke olesup "setOLETerminateOption" using by value option
| 0 | Only allow the server to terminate if no windows are visible. |
| 1 | Only allow the server to terminate if no windows are visible, apart from a console window. (An OO COBOL GUI application opens a console window if your application uses DISPLAY statements.) |
| 2 | Allow the server to terminate regardless of any windows open (this is the default behavior). |
Copyright © 2006 Micro Focus (IP) Ltd. All rights reserved.