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.
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
|