More about user objects and the registry
The registry stores information required by a program for
it to access a registered object. The information is stored in the
registration database. To update the registry, the Registry Editor
reads registry update files (REG) and inserts
the information in the database.
What are all the identifiers for?
GUIDs and CLSIDs
A globally unique identifier (GUID) is a 128-bit integer that
is virtually guaranteed to be unique. You can generate your own
using the PowerBuilder.Application GenerateGUID function.
The formula is based on the time of day, the date, and a unique
number contained in your network card. If you do not have a network
card, you can request GUIDs from Microsoft in sets of 256.
GUIDs are used as class identifiers (CLSID) to uniquely identify
each object and type library. The CLSID enables a program to be
sure of the interface that it is interacting with.
ProgIDs
Programmatic identifiers (ProgID) are unique only in the local
environment. They may contain up to 39 characters, must not contain
any punctuation (except for the period), and must not start with
a digit. They have two forms:
- Version-independent Does not include a version number
1<i>applicationname</i>.<i>objectname</i>
For example, MyApp.Application or MyApp.AnalysisUserObject - Version-dependent Includes a version number
1<i>applicationname.objectname.versionnumber</i>
For example, MyApp.Application.1 or MyApp.AnalysisUserObject.1
You should establish consistent naming conventions for your
applications and objects so that others can see the relationships
among your objects.
Other programmers use the ProgID to connect to objects that
you register. If they specify the version-independent ID, the registry
redirects them to the current version.
When you use the PowerBuilder.Application function GenerateRegFile,
you supply a version-independent ProgID and PowerBuilder constructs
the version-dependent entry using the version number you specify.
Where information about your object is stored
Information about a registered object is stored in the registry
in three or four places. There is a section for a:
- CLSID
- Version-dependent ProgID
- Version-independent ProgID
- Type Library (optional)
All this cross-referencing ensures that an object’s
information can be found no matter what the program starts with.
Keys and their subtrees
The PowerBuilder.Application functions update the tree HKEY_CLASSES_ROOT.
The other keys in the registry reflect this information for a particular
context.
Subkeys
Information for each entry is stored in subkeys, which are
a level below the entry subkey. Some subkeys have values, such as
a file name. Others have meaning just because they are there, such
as NotInsertable.
Each entry and its associated subkeys is described below.
ProgID
The list of registered ProgIDs appears in the registry under
this key:
1 |
My ComputerHKEY_LOCAL_MACHINESOFTWARECLASSES |
Both version-dependent and version-independent ProgIDs appear.
The ProgID is a cross-reference to the object’s CLSID.
Subkey | Value |
---|---|
CLASSESProgID | Description of object |
CLASSESProgIDCLSID | The object’s CLSID |
CLASSESProgIDCurVer (for the version-independent entry only) |
The version-dependent ProgID |
CLASSESProgIDNotInsertable | Empty string |
CLSID
Under the CLASSES key is a subkey CLSID that
lists all the registered CLSIDs. Each CLSID records all the information
about the registered object:
1 |
My ComputerHKEY_LOCAL_MACHINESOFTWARECLASSESCLSID |
Subkey | Value |
---|---|
CLASSESCLSID{guid} | The GUID for the object. |
CLASSESCLSID{guid}InProcServer32 | The path and file name for the PowerBuilder runtime DLL. |
CLASSESCLSID{guid}NotInsertable | “” |
CLASSESCLSID{guid}PowerBuilder | Not set. Subkeys store information about the object’s environment (see below). |
CLASSESCLSID{guid}Programmable | “” |
CLASSESCLSID{guid}ProgID | The ProgID you specified with the current version number. |
CLASSESCLSID{guid}TypeLib | The CLSID for the type library. |
CLASSESCLSID{guid} VersionIndependentProgID |
The ProgID you specified without a version number. |
PowerBuilder subkey under CLASSESCLSID | Value |
---|---|
{guid}PowerBuilderBinaryType | The type of code in the library, either compiled machine code (MCODE) or Pcode |
{guid}PowerBuilderLibraryList | The name of the library that contains the object |
{guid}PowerBuilderClassName | The object’s name in the library |
TypeLib
Under the CLASSES key is another subkey
for TypeLib.
1 |
My ComputerHKEY_LOCAL_MACHINESOFTWARECLASSES |
1 |
TypeLib |
Subkey | Value |
---|---|
CLASSESTypeLib{guid} | The GUID for the type library. |
CLASSESTypeLib{guid}VersionNum | The version number of the type library.
A tree of subkeys is below the version number, allowing entries VersionNumLanguageIDWin32 specifies |
CLASSESTypeLib{guid}FLAGS | 0 |
CLASSESTypeLib{guid}HELPDIR | The directory where a Help file is located. |
Creating registry information
A client application uses the registry to find the information
required to access your user object. The registry includes information
about where to find the files for the PowerBuilder runtime environment
and the libraries. It can also contain a pointer to a type library
file that documents the properties and methods of the object. When
the type library is registered, it lets the user examine the object in
an OLE browser. (Instance variables of the object appear as properties
in the OLE browser.)
PowerBuilder.Application provides facilities for generating
the necessary registry information. To add your object to the registry,
you need a registry update file, which contains information to be
added to the system’s registration database. The type library
is optional–you need it if you want others to be able to
inspect your object’s properties and methods in an OLE
browser.
To use these functions, you must run a client application
that connects to PowerBuilder.Application. (You can run the client
application in the development environment.)
Functions for generating registry information include:
- GenerateGUID Gets a valid globally unique identifier to serve as the CLSID
of your object and its type library - GenerateRegFile Uses the properties of PowerBuilder.Application and other values
to generate a registry update file that the Registry Editor (REGEDT32.EXE)
can use - GenerateTypeLib Uses the information in the object to generate a type library
and updates the registry file with information about the type library
You can use these functions yourself, as shown in the example
below, or you can use an installation application that provides
tools for creating registry information, such as InstallShield.
Deploying and the registry The registry file that you create on your computer can be
used to register your object on your own computer. The path information
for files (the object library and the type library) is specific
to your machine and is probably not applicable to other machines.
To deploy your object, you need to modify the registry update files
according to the directories the user specifies for installation,
or call functions for modifying the registry itself.
See “Deploying an application
that uses the automation server “.
Sample script for generating registry information
This script takes information from several SingleLineEdit
controls and a CheckBox and builds a registry update file and a
type library. The script hard-codes version information,
but you can use edit boxes to obtain version information too.
The SingleLineEdits and CheckBox used in the following example
are shown in Table 20-6.
Object for input | Data provided |
---|---|
sle_object | The name of the object in the PowerBuilder library |
sle_progid | A programmatic identifier you supply |
sle_desc | A description of your object, which is displayed in the registry |
sle_regfile | The name of the registry update file you want to generate |
sle_typelibfile | The name of the type library file you want to generate |
sle_library | The name of the PowerBuilder library containing the object |
cbx_machinecode | Whether the library uses compiled code or Pcode |
This program generates a registry update file and type library.
1 |
oleObject ole_pb |
1 |
string ls_reg_guid, ls_tlb_guid |
1 |
long ll_result, ll_res2 |
1 |
1 |
// Connect to the PowerBuilder.Application server |
1 |
ole_pb = CREATE oleObject |
1 |
ll_result = ole_pb.ConnectToNewObject & |
1 |
("PowerBuilder.Application") |
1 |
IF ll_result < 0 THEN |
1 |
MessageBox( "Can't Connect", & |
1 |
"Error connection to PowerBuilder.Application") |
1 |
RETURN |
1 |
END IF |
1 |
1 |
// Set properties for the server session, which |
1 |
// will become the values for the registered object |
1 |
ole_pb.LibraryList = sle_library.Text |
1 |
ole_pb.MachineCode = cbx_machinecode.Checked |
1 |
1 |
// Get GUIDs for the object and type library |
1 |
ll_result = ole_pb.GenerateGUID( REF ls_reg_guid) |
1 |
ll_res2 = ole_pb.GenerateGUID( REF ls_tlb_guid) |
1 |
IF ll_result < 0 THEN |
1 |
MessageBox( "Can't Get GUID", & |
1 |
"Generating GUID for Reg file failed.") |
1 |
RETURN |
1 |
ELSEIF ll_res2 < 0 THEN |
1 |
MessageBox( "Can't Get GUID", & |
1 |
"Generating GUID for TypeLib file failed.") |
1 |
RETURN |
1 |
END IF |
1 |
1 |
// Use info from user to generate registry update file |
1 |
// Arguments for GenerateRegFile: |
1 |
// valid GUID |
1 |
// Name of uo in PB library |
1 |
// ProgID as in registry |
1 |
// Major version, Minor version |
1 |
// Description |
1 |
// Name of reg file |
1 |
ll_result = ole_pb.GenerateRegFile( & |
1 |
ls_reg_guid, & |
1 |
sle_object.Text, & |
1 |
sle_progid.Text, & |
1 |
1, 0, & |
1 |
sle_desc.Text, & |
1 |
sle_RegFile.Text ) |
1 |
IF ll_result < 0 THEN |
1 |
MessageBox("Can't generate RegFile", & |
1 |
"result code is " + String(ll_result) ) |
1 |
RETURN |
1 |
END IF |
1 |
1 |
// Use information that matches the registry update |
1 |
// file to generate the type library |
1 |
// Arguments for GenerateTypeLib: |
1 |
// |
1 |
// GUID in Reg file |
1 |
// Name of uo in PB library |
1 |
// Prog ID as in Reg file |
1 |
// Locale, Major version, Minor version |
1 |
// Description |
1 |
// Help context, Help file |
1 |
// GUID for TypeLib |
1 |
// Name of typelib file |
1 |
// Name of reg file |
1 |
ll_result = ole_pb.GenerateTypeLib( & |
1 |
ls_reg_guid, & |
1 |
sle_object.Text, & |
1 |
sle_progid.Text, & |
1 |
0, 1, 0, & |
1 |
sle_desc.Text, & |
1 |
0, "", & |
1 |
ls_tlb_guid, & |
1 |
sle_typelibfile.text, & |
1 |
sle_regfile.text) |
1 |
IF ll_result < 0 THEN |
1 |
MessageBox("Can't generate TypeLib File", & |
1 |
"result code is " + String(ll_result) ) |
1 |
RETURN |
1 |
END IF |