ActiveX
Components

Register (and Unregister)


by Rick Meyer         Home

Table

of

Contents


1. A brief explanation of COM
2. A brief explanation of ActiveX
      a. DLL's and EXE's
      b. Registration is required
3. Visual Basic registers your components automatically
4. Installing your program on another computer.
      a. The registered location is important.
      b. A brief discussion of the path.
5. Regsvr32.exe commands for DLL's and OCX's
6. Registration commands for EXE's
7. The RegX Visual Basic project
COM (short for Component Object Model) is a specific convention for allowing objects to interact with one another in an orderly, predictable way. Due to the number of programming languages and operating systems, some standard has to be set for the various objects created by these languages and systems if they want to work together. COM is one such standard.
ActiveX© is based on COM. It allows Visual Basic programmers to create code libraries for repetitive code or instancing of whole server objects. ActiveX DLL's will provide same code thread execution while EXE's provide a separate code thread. Although it is possible to make an ActiveX standalone EXE program, the intent is to create these as code libraries that your (standard EXE) program may access.

In Visual Basic, ActiveX components are programmed as classes. Class, Client and Server are object-oriented programming terms. A client normally creates an instance of a server class and then sends information and requests to that instance. The server then processes the information and usually returns some information to the client. Generally the ActiveX object is the server and your standard EXE is the client.

When Microsoft implemented ActiveX for its Windows© operating system, to comply with the COM standard they set up a system whereby any and all ActiveX components (libraries generally - but just might be a standalone program) must be registered with the operating system before they can be used. Among the advantages, such registration enables Windows to ensure beforehand that a component is ActiveX compliant - thus not tying up the system with repetitive system overhead checks (speeding execution of your library requests).

Visual Basic automatically registers your ActiveX components for you each time you compile an ActiveX project. Included in the system registration information is the path and file name of the DLL or EXE you have just compiled. (So you only need to specify the name of the desired component and Windows knows where to find it.) For your Visual Basic projects you may be creating and registering this DLL or EXE in a directory where your source code is located.
Similiarly when your program is installed on another computer, it will not run unless your DLL (and a lot of other VB DLL's) is first copied to that computer and then registered. (You must run the application setup wizard to produce the installation file with all these required dependent files.)

If a program has already been installed on another computer, then the rules of COM should allow reregistration of a reprogrammed component with no recompile of the standard EXE client if the signature (anything public about the component) of the ActiveX component has not changed. ActiveX and VB take it one step further and require recompile of your standard EXE any time the ActiveX component has been reregistered.

The registered location is important. If you move the DLL or EXE to another directory, Windows can't find it and your (compiled) program won't run. Note that Microsoft did not initiate this process to be an added security feature, but to assist in ensuring compatibility with the COM standard of which ActiveX is a subset.

The path is a DOS environmental variable where the system will search for files automatically if you have not included the full path in your filespec. c:\windows, c:\windows\system, and c:\windows\system32 are usually set as the path. Normally you will find ActiveX files in the path (in c:\windows\system or c:\windows\system32). They are copied there when applications are installed on a computer. For your own personal use it is fine to keep your ActiveX components registered in the source code directory where you compiled them. But if you wish to move them to c:\windows\system, you must register them again. (I like to unregister the old location first.)

The windows program named c:\windows\regsvr32.exe is used to register and unregister ActiveX DLL's and OCX's. (An OCX file is merely a renamed DLL file.) You RUN regsvr32 as follows:
                 Register:  regsvr32 dllFileName.dll
               UnRegister:  regsvr32 /u dllFileName.dll
The above example assumes that the target "dllFileName.dll" is in your computer's path. (Regsvr32 is also assumed in the path.)
To issue the command in Windows:

1.  From the Start Menu select Run
2.  Type in the command like: regsvr32 /u dllFileName.dll
3.  Click OK.

You should get a message as to the success of your command.
If your component is not in the path and the path to your component contains a space in it, you will need to enclose the filespec in quotes when you issue the command like this.
       Register:  regsvr32 "c:\program files\vb\dllFileName.dll"
     UnRegister:  regsvr32 /u "c:\program files\vb\dllFileName.dll"
ActiveX EXE's have a slightly different process. You do not use Regsvr32.exe to register them. Instead they basically register and unregister themselves, and you accomplish this by running them with the proper command line parameter.
       Register:  ActivexFileName.exe /regserver
     UnRegister:  ActivexFileName.exe /unregserver

                            or

       Register:  "c:\program files\vb\ActivexFileName.exe" /regserver
     UnRegister:  "c:\program files\vb\ActivexFileName.exe" /unregserver
Generally you can easily browse for your EXE file in Start->Run and then just add the /regserver part before clicking OK.
The following RegX Project is a program I wrote for my own personal use to more easily browse for my ActiveX components and then choose to either register or unregister them.
    Instructions for Building this Project:

1. Start a new standard exe.
2. On Form1 put 3 CommandButtons named Command1-3.
3. On Form1 put a Label named Label1.
4. On Form1 put a Textbox named Text1.
5. In Project->Components add Microsoft CommonDialog Control
6. On Form1 put a CommonDialog named CommonDialog1.

There is no need to position or size the above controls
on the form since that is all done in the Form_Load.

Now you are ready for the code. Select all of the following code (by clicking on the word 'Option' three times) and copy it to the clipboard [Ctrl][Insert]. Then paste it into the code window of Form1 with [Shift][Insert]. Variable Key
% As Integer
& As Long
! As Single
# As Double
$ As String
When you run the program, click on the Browse button to bring up the common dialog window. You will then be able to choose an ActiveX file. Click the Register button to register it or the Unregister button to unregister it.
'========================================================
'                        RegX
'        by: Rick Meyer       date: July 2001
'========================================================
' File Name:   regx.frm
' Object Name: Form1
' Description: Interface and code for registering and
'              unregistering ActiveX DLL OCX, & EXE
'========================================================

Option Explicit

Private Enum regxEnum
    REGISTER
    UNREGISTER
End Enum

Private Enum resultEnum
    INVALID
    NOTFOUND
    NOTACTX
    NOTHREAD
    SUCCESS
    FAILURE
End Enum

' The API's to be used
Private Declare Function ShellExecute _
    Lib "shell32.dll" Alias "ShellExecuteA" ( _
    ByVal hwnd As Long, _
    ByVal lpOperation As String, _
    ByVal lpFile As String, _
    ByVal lpParameters As String, _
    ByVal lpDirectory As String, _
    ByVal nShowCmd As Long) As Long

Private Declare Function LoadLibraryRegister _
    Lib "KERNEL32" Alias "LoadLibraryA" ( _
    ByVal lpLibfName As String) As Long

Private Declare Function FreeLibraryRegister _
    Lib "KERNEL32" Alias "FreeLibrary" ( _
    ByVal hLibModule As Long) As Long

Private Declare Function GetProcAddressRegister _
    Lib "KERNEL32" Alias "GetProcAddress" ( _
    ByVal hModule As Long, _
    ByVal lpProcName As String) As Long

Private Declare Function CreateThreadForRegister _
    Lib "KERNEL32" Alias "CreateThread" ( _
    lpThreadAttributes As Any, _
    ByVal dwStackSize As Long, _
    ByVal lpStartAddress As Long, _
    ByVal lpparameter As Long, _
    ByVal dwCreationFlags As Long, _
    lpThreadID As Long) As Long

Private Declare Function GetExitCodeThread _
    Lib "KERNEL32" ( _
    ByVal hThread As Long, _
    lpExitCode As Long) As Long

Private Declare Sub ExitThread _
    Lib "KERNEL32" ( _
    ByVal xc As Long)

Private Declare Function CloseHandle _
    Lib "KERNEL32" ( _
    ByVal hObject As Long) As Long

Private Declare Function WaitForSingleObject _
    Lib "KERNEL32" ( _
    ByVal hHandle As Long, _
    ByVal dwMilliseconds As Long) As Long


' The Main Function to do the work
Private Function RegX(fName$, func As regxEnum) _
                                    As resultEnum
    Dim regLib&, process&, succeed&
    Dim h1&, xc&, id&
    Dim p$
    
    Select Case func
        Case REGISTER: p = "DllRegisterServer"
        Case UNREGISTER: p = "DllUnregisterServer"
        Case Else: RegX = INVALID: Exit Function
    End Select

    regLib = LoadLibraryRegister(fName)
    If regLib = 0 Then
        RegX = NOTFOUND
        Exit Function
    End If
        
    process = GetProcAddressRegister(regLib, p)
    
    If process = 0 Then
        RegX = NOTACTX
    Else
        h1 = CreateThreadForRegister(ByVal 0&, 0&, _
            ByVal process, ByVal 0&, 0&, id)
        
        If h1 = 0 Then
            RegX = NOTHREAD
        Else
            succeed = _
                (WaitForSingleObject(h1, 10000) = 0)
            If succeed Then
                CloseHandle h1
                RegX = SUCCESS
            Else
                GetExitCodeThread h1, xc
                ExitThread xc
                RegX = FAILURE
            End If
        End If
    End If

    FreeLibraryRegister regLib
End Function

'Handle differently if it is an EXE
Private Function ItIsNotEXE(func As regxEnum) As Boolean
    ItIsNotEXE = False
    
    Text1.Text = Trim$(Text1.Text)
    If Len(Text1.Text) < 5 Then Exit Function
    
    If LCase$(Right$(Text1.Text, 3)) <> "exe" Then
        ItIsNotEXE = True
        Exit Function
    End If
    
    Dim sWorkDir$, sFile$, sCommand$
    
    sFile = Text1.Text
    sWorkDir = vbNullString
    sCommand = IIf(func = REGISTER, _
        "/regserver", "/unregserver")

    Label1.Caption = Str$(ShellExecute(Me.hwnd, _
        "open", sFile, sCommand, sWorkDir, 1))
End Function

'The Register Button
Private Sub Command1_Click()
    If ItIsNotEXE(REGISTER) Then
        showLabel RegX(Text1, REGISTER), ""
    End If
End Sub

'The Unregister Button
Private Sub Command2_Click()
    If ItIsNotEXE(UNREGISTER) Then
        showLabel RegX(Text1, UNREGISTER), "Un"
    End If
End Sub

Private Sub showLabel(x As resultEnum, u$)
    Dim s$
    
    Select Case x
        Case INVALID:  s = "Invalid function"
        Case NOTFOUND:  s = "Could not find file"
        Case NOTACTX:  s = "File is not ActiveX"
        Case NOTHREAD:  s = "Could not create thread"
        Case SUCCESS:  s = u & "Register Successful"
        Case FAILURE:  s = u & "Register Failed"
    End Select
    
    Label1.Caption = s
End Sub

'The Browse Button
Private Sub Command3_Click()
    Static InitDir$

    If InitDir = "" Then
        InitDir = "C:\Windows\System"
    End If
    
    With CommonDialog1
        .InitDir = InitDir
        .FileName = ""
        .Filter = "ActiveX Files|*.ocx;*.dll*;*.exe"
        .ShowOpen
        
        Text1.Text = .FileName
        InitDir = .FileName
    End With
End Sub

Private Sub Form_Activate()
    Command3.SetFocus
End Sub

Private Sub Form_Load()
    Const UNIT = 375
    Dim tp!, lt!, rt!, tw!, lt2!
    
    tp = UNIT
    lt = 200
    rt = ScaleWidth - lt
    tw = (rt - lt - UNIT) / 2
    lt2 = (ScaleWidth + UNIT) / 2
    
    Caption = "RegX - ActiveX Register and Unregister"
    
    With Text1
        .Text = ""
        .Move lt, tp, rt - lt, UNIT
    End With
    
    tp = tp + UNIT * 2
    With Command1
        .Caption = "Register"
        .Move lt, tp, tw, UNIT
    End With
    With Command2
        .Caption = "Unregister"
        .Move lt2, tp, tw, UNIT
    End With
    
    tp = tp + UNIT * 2
    lt2 = (ScaleWidth - tw) / 2
    With Label1
        .Caption = ""
        .Move lt2 - UNIT, tp, tw + UNIT * 2, UNIT
    End With
    
    tp = tp + UNIT * 2
    With Command3
        .Caption = "Browse"
        .Move lt2, tp, tw, UNIT
    End With
End Sub