Creating an automation DLL

In this chapter an existing application is converted to an in-process automation DLL.

In and out of process

In the first chapter I added automation to an existing application. This enabled external Automation clients to make calls to code inside a Delphi form. These calls are made out of an external exe into my Delphi exe, from one Windows process to another Windows process. This is called an out-of-process automation server. Crossing process boundaries is an expensive operation. Some information even cannot be passed across process borders. 

Windows has a very well defined standard for making in-process calls to other code in the same process. This is the Dynamic Link Library, the external code is linked at runtime in the client using the code. This technique is used in automation in-process servers.

Creating the DLL

An automation DLL is called an ActiveX library. To create a new library go to the File | New | Other menu and pick  library

Having done this, the first thing you have to do is save the project. Otherwise you will be stuck with an automation class which is named project1. Here I will deliberately use the same name for the project as in the out-of-process project : FileManager. Now we have an empty typelibrary. The in-process automation object is created in the same way as the out-of-process automation object, the automation object wizard can be used again to create the class. Also this class will get the  same name as its out-of-process counterpart : FileZapper. (For all interesting consequences of this, see the chapter on using automation objects)

We end up with an empty DLL and can start adding the properties and methods. It would be quite a waste of time and effort to reenter all definitions again. The Delphi type library editor is a good two way tool on the text level. Which means I can copy the text representation of the former IFileZapper definition and paste this into the new IfileZapper definition. I take the former project, open the typelibrary and select the text representation of IfileZapper.

Note that the selection starts after the opening bracket ({) and ends before the closing bracket (}). After copying the selection to the clipboard I open the new typelibrary and select the same piece of text

Pasting the text will now do the magic. All properties and methods appear in the tree view of the editor. Refreshing will create skeletons for all method- and property-implementations. 

Reusing code

At this point there is another piece of work which can be copied. As the implementations of the methods and properties will stay the same I can copy the .pas unit from the previous project. It is important to know how the Delphi typelibrary editor links an interface definition in the typelibrary to a Delphi unit containing the implementation. This is defined in the project file:

library FileManager;

uses
ComServ,
FileManager_TLB in 'FileManager_TLB.pas',
FileZapper in 'FileZapper.pas' {FileZapper: CoClass},

The directive {FileZapper: CoClass} is used by the typelibrary editor to find the unit. If I give my new implementation unit the same name as the old one all is fine. Else I will have to change the directive in the .dpr. Note that I will have to reopen the project after fiddling with this directive.

To finish off I will copy the form with the application code and will add this to the project. 

Please note that you cannot reuse the Filemanager_tlb unit. When you compare the former version with the new version you will notice differences in the values of the Guids. Automation (COM) internally fully depends on these guids, having wrong value's will result in very strange behaviour. More on this in the chapter on  using automation objects.

Creating the form

In the out-of-process version the form was automatically created on launching the exe. In the in-process DLL I will have to do this manually. Here some nice methods from the vcl come in handy. tObject has an AfterConstrucion and a BeforeDestruction method. A tObject can have a variety of constructors and destructors, the two methods will always be called after the last constructor has finished and before the first destructor will start. I will include a private Form1 variable in the Filezapper class and will use the methods to manage the form.

procedure TFileZapper.AfterConstruction;
begin
  inherited;
  Form1:= TForm1.Create(nil);
  Form1.Show;
end;

procedure TFileZapper.BeforeDestruction;
begin
  Form1.Free;
  inherited;
end;

A Delphi automation object is not a Delphi component, so there is no owner to pass to the constructor of tForm1. This means I will have to free the form  myself. Which is done in BeforeDestruction.

Registration of the server

An automation object has to be registered to let potential clients know it exists and tell them how to create it. An out-of-process server (exe) server registers itself when it is run the first time. An in-process server has to be registered by hand. This is integrated in the Delphi IDE. In the Run menu you will find the Register ActiveX Server item. Selecting that will build the DLL, register it and report the result. 

Debugging the DLL

A DLL cannot run itself. It will need some kind of client to load it. To debug the DLL the Delphi IDE can load  a host application. I will test this server while it is being used by MS-Word. In the Run | Parameters the host and its parameters are set

The result of this is that starting the DLL in the Delphi IDE will result in Word starting and opening the FileManagerDocument. A macro in this document will load the filemanager server. The macro's code is not the best way to use an automation object in Word, for the moment it is just the simplest way.

Dim MyManager

Sub UseManager()
Set MyManager = CreateObject("FileManager.FileZapper")
    MyManager.Directory = "C:\"
    MyManager.Filemask = "*.doc"
    MyManager.AllowDelete = True
End Sub

Executing the macro will pop up the filemanager form. Closing the document will destroy the form. How al of this works is explained in the chapter on automation object management. In this chapter you will find a better way to use the object in Word as well. 

What can be seen here is that you can set breakpoints in the source which will respond as Word does things with your automation object.

Where are we ?

We have seen the difference between in- and out- of process automation servers. The latter, implemented as DLL's, are a lot faster but do not require any different coding. The only difference compared to the standalone exe is the management of the application's main form. 

What's next ?

  • Using automation objects
  • Advanced properties
  • Understanding objects and interfaces
  • Demo application