The new vbAccelerator Site - more VB and .NET Code and Controls
 Installing, Registering, COM and VB
  What is a ProgID and How Do I Change It?  
  Information about ProgIDs, CLSIDs and a little about COM object registration  
 

If you are modifying an ActiveX EXE, DLL or OCX you have downloaded from this site and want to distribute it with your project, I specify two requirements:

  • Change the filename
  • Change the ProgID
So, you ask, just what is a ProgID anyway, and how or why do I change it? This article is here to explain. If you don't want to know why, just skip straight to Changing a ProgID.
All About ProgIDs and a Little About COM
VB implements non-private Classes and UserControls as COM objects (I suppose I should mention that UserDocuments are also done this way too, but who uses them?) To allow access to a COM object regardless of where it is located, COM implements a mechanism to identify where the executable implementing a given COM object is. This mechanism means COM is not restricted to any given path for storing an object, and with the DCOM extensions the COM object can actually be held on another computer on the network.

To do this, COM requires that every non-private object has a unique identifier. This identifier is called a GUID (Globally Unique Identifier). This is a 128bit number (thus potentially allowing for a maximum of 2128 possible COM objects, which is an undescribably large number. Read about how GUIDs are generated here). To make it easier to write a GUID, it is normally expressed as a hexadecimal number with some formatting applied. This form of a GUID is also referred to as a CLSID when the GUID is the identification number for a COM object. An example CLSID looks like this (this is the CLSID for the Microsoft Common Dialog control shipped with Service Pack 2 of VB5):

  {F9043C85-F6F2-101A-A3C9-08002B2F49FB}

The formatting shown corresponds to the COM GUID type:

  Type GUID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(0 To 7) As Byte
  End Type

Even with this formatting, a GUID is hardly an easy thing to remember. In addition to this, COM supports the concept of Binary Compatibility where two objects with different GUIDs can be used interchangeably.

To allow for Binary Compatible objects and to make it easier to get at COM objects, a higher level of abstraction from the GUID exists. This is the ProgID (Programmatic IDentifier). The Programmatic ID is a string of the form:

  Project.ClassName

For example, the ProgID for the Word automation object is Word.Basic. In a Visual Basic project, the ProgID is determined in a logical way: from the Project Name and the Class Name. So for example, the vbAccelerator Flat Control Extender DLL is implemented in a project named vbalFCtrl and has one Public class called cFlatControl. The ProgID is therefore:

  vbalFCtrl.cFlatControl

This information is stored in the registry like this:

HKEY_CLASSES_ROOT
  vbalFCtl.cFlatControl
    CLSID
      (default) = "{E16E3DC5-B228-11D2-8E21-44C10AC10000}"


  CLSID
    ..
    {E16E3DC5-B228-11D2-8E21-44C10AC10000}
      InProcServer32
       (default)="C:\Stevemac\VB\Develop\FlatCtrl\DLL\vbalFCtl.dll"
       ThreadingModel="Apartment"
    ..

When you request an instance of the cFlatControl class, COM looks up the ProgID "vbalFCtl.cFlatControl" which gives it the GUID of the object. COM can then locate the GUID and therefore the path to the object. This is where the problem arises with two objects with the same ProgID. If you create a new version of the Flat Control DLL, say it either has with different methods or it is compiled in VB6 instead of VB5, you will automatically generate a new GUID. However, if you don't change either the project name or the class name, you will overwrite the existing ProgID with your own version. Anyone else's code which expects to get an instance of the object suddenly gets routed to the new version, and their code may then fail depending on what you've done to the existing class.

TopBack to top

Changing a ProgID
That's why you need to change the ProgID. There are two options you can use to actually change one. Firstly you can change the Project Name, and secondly you can change the Class Name. The most commonly used strategy is to change the Project Name component (CCRP and Microsoft take this approach). This means that your new version is a completely new component, and you have to recompile any existing code to use it, plus you need to unreference the previous version of the component and select the new one instead.

Changing the Project Name
Changing the Project Name in Visual Basic
This is a fairly painless operation for DLL components. Since the class name is unchanged, your previous code should just work by changing the reference in the Project-References box.

For controls, however, this isn't so easy. Controls can persist a great quantity of information entered at design time in your form's FRX files. Removing the control and adding the new one throws away all of this information. You can see this particularly with the ImageList control. If you have an ImageList control with 90 icons in it, to migrate to a new version of the component means you have to somehow get all 90 icons from the previous version to the new one. Often you can make this change quite easily by adjustment of VB's Project and Form files. Say for example you were migrating the pre-release demo of the S-Grid control from a VB5 version to the VB6 version.

In the Project file you will have something like this:

Object={7800BB88-99A6-11D2-8E21-6C8804C10000}#22.0#0; vbalGrid.ocx

And in the form file:

Object = "{7800BB88-99A6-11D2-8E21-6C8804C10000}#22.0#0"; "vbalGrid.ocx"

...

   Begin vbAcceleratorGrid.vbalGrid grdThis
     Height = 3735
     Left = 0
     TabIndex = 0
     Top = 180
     Width = 5175
     _ExtentX = 9128
     _ExtentY = 6588
     BackgroundPictureHeight= 0
     BackgroundPictureWidth= 0
     GridLineColor = 12632256
     BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851}
       Name = "Tahoma"
       Size = 8.25
       Charset = 0
       Weight = 400
       Underline = 0 'False
       Italic = 0 'False
       Strikethrough = 0 'False
     EndProperty
   End

You should find you can migrate from one version to another by replacing the CLSIDs in both files (see above for how to determine the new CLSID) and changing the ProgID in the form file from the old version to the new one you have compiled (from vbAcceleratorGrid.vbalGrid to, say, vbAcceleratorGrid6.vbalGrid). Of course here I am assuming the the StdFont object used to persist the font information hasn't changed its CLSID as well. To make sure you have your CLSIDs correct, you can create a blank project, add the new control and put some dummy design time data in. Then open up the test project's .vbp and .frm files - you will be able to see the new CLSIDs and ProgIDs and should be able to swap them over!

Changing the Filename
Oh, and when you do all this, don't forget to change the filename at the same time! Although you can in theory have two different ActiveX controls or DLLs files with the same name, there are two problems here:

  • Multiple files with the same names mean the system is pretty much unmanagable. Which file is which?
  • At heart ActiveX controls or DLLs are still Win32 DLLs and therefore subject to the limitations of the operating system. Under Win9x you particularly have problems because the first version to be loaded with then determine what every other application on the system uses.



TopBack to top

BackBack to Installation

BackBack to Home

 
 

About  Contribute  Send Feedback  Privacy

Copyright © 1998-1999, Steve McMahon ( steve@vbaccelerator.com). All Rights Reserved.
Last updated: 17 February 1999