VB6 Programmer's Introduction to COM Check out the latest essential read from Thomas Lewis and Wrox Press! This top tome teaches you the ins and outs of the Microsoft Component Object Model, and explains the part it plays in all of today's technologies, including ActiveX and OLE.
The Microsoft Component Object Model, lovingly referred to as COM, is probably the most
mysterious acronym yet to come from our friends in Redmond. Speak with any Visual Basic
programmer and ask them a very simple question: What is COM?
- "It is the glue for Microsoft applications."
- "It lets you create components."
- "It allows software objects to talk to other software objects."
- "It is a standard for components."
- "I don't know, I just work here."
You will find that almost everyone you speak to will have a different view of what COM
is, but it would be unfair to lay the blame for this confusion at the door of the
programmer. The standard marketing definitions are not well known because COM is not a
product you can go down to the store and purchase. In addition, Microsoft has not made
things any easier, since it seems to change the definition each time a new set of
PowerPoint slides are shown to the public.
When I decided that I wanted to know what this "COM" thing was and what it
meant to me as a Visual Basic programmer, I knew I was on a journey. You can think of this
book as the field notes I made on that trip. Luckily, I found that with Visual Basic as my
guide, I was able to take quite a few shortcuts, so put your hiking boots on and let's hit
From this point forward, I will refer to the Component Object Model as COM.
In this section, I'm going to attempt to define COM in a piece-by-piece fashion. Let's
start with the basics and cover what the letters C-O-M stand for.
Components and Objects
Components and objects are key concepts in COM, but like "COM" itself, the
words are often misused and can mean different things to different people. This is because
the terms are tricky first to define and then to distinguish, and for that reason I intend
to leave doing so until a more rigorous discussion in the next chapter. I want to keep
this introduction at a higher level, and so I shall begin by explaining some of the
concepts of component-oriented design without going too deeply into what actually makes a
Traditionally, applications were distributed in single, large executable files, which
are now known as monolithic applications. These had many inherent problems, paramount of
which was that if one line of code needed to be changed, then the entire application
needed to be rebuilt. This made the development and maintenance of such applications
problematic at best.
Component-oriented design circumvents these problems by breaking applications down into
components that can be distributed in separate binary files - either dynamic-link
libraries (DLLs) or executables (EXEs). In this context, components are pre-compiled,
interacting pieces of software that can act as 'building blocks' for creating
applications. In some ways, these components can be thought of as raw elements: in the
same way that chemical elements can be combined in a multitude of ways to create different
compounds, components can be combined to create different applications. Although COM is
not essential for component-oriented design, it does make the entire process considerably
easier to implement.
The idea is that a given component can be re-used in different applications that
require similar functionality. So, for example, you could construct an invoicing component
for one application that could then be reused in other applications that also require an
Another advantage of this mode of design is that it allows the individual components of
an application to be updated easily. Only one of the comparatively small binary files
needs to be replaced, unlike in the old monolithic case where the entire application had
to be recompiled in order to reflect changes in the source code.
Interfaces are really what COM is all about. I shall cover them in far greater detail
in the next chapter (and indeed throughout the rest of the book). Basically, the
interfaces of a component are the mechanism by which its functionality can be used by
another component. The precise structure of an interface is defined by COM, but in essence
it's just a list of functions implemented by the component that can be called by other
pieces of code.
At this point, a brief discussion of clients and servers would probably be beneficial,
as we'll be talking about them a lot throughout the book.
Clients and Servers
The term 'client/server' encapsulates two separate, discrete entities. These entities
could simply be two components, two applications or even two computers. The client
requires some service, and requests a server to perform this service on its behalf. The
server performs the service and, if required, returns a result to the client.
For example, a client may need some data from a database. In this case, the server
could simply be the database, or there could be some additional objects between client and
database. In the latter case, these objects would be the 'server' from the client's point
of view. From the database's angle, however, the objects form the client and the database
is the server. In other words, the client/server distinction merely refers to a request
for a service or services. The client does the requesting, and the server performs the
In terms of COM components, each component can act as both client and server. A server
is a component that exposes interfaces and therefore a list of functions that a client can
call. It follows that the client is a component that uses that interface.
COM enforces a strict separation of the client and server such that they only know of
each other's presence by the existence of their interfaces. To a COM client, the server is
really just a set of interfaces, and I'll have more to say on this subject in the next
Throughout the rest of the book, I'll be developing this definition of a component and
A Quick Aside
Again, don't worry about the definitions of components and interfaces; for now I just
want to draw your attention to how they are drawn in these COM diagrams. The large box
represents a component or an object, while the "blobs on sticks" represent the
interfaces exposed by that object. For obvious reasons, COM diagrams like this one are
sometimes called lollipop diagrams.
If we follow the COM model we will create components described in such a way that they
can interact with one another at runtime. The COM model specifies what the interfaces of a
component must look like at the binary level, which means that provided your programming
language can produce code that obeys the specification, it doesn't actually matter which
one you use. This is how COM's much-vaunted language independence is achieved.
Defining COM in a few words is not the easiest thing to do because it comprises several
things. Let's expand on the explanations I've given so far by examining exactly what it is
that COM provides.
COM is a framework for creating and using components
Because COM is a language-independent standard, it's possible to build and subsequently
use components with different languages such as Visual Basic, Visual C++, Delphi or Visual
J++. A COM client (sometimes also called a container) is an application whose architecture
supports the use of these software components.
COM provides a mechanism for components to communicate with each other
COM achieves the communication promised by the title of this section by the combination
of two things. First, there is the binary standard it imposes, which means that your
components not only provide a mechanism to communicate, but also know how to speak to
other COM-enabled components or applications.
Second, there is the set of services provided by the COM runtime (also called the COM
library) that is required to be present on a computer before communication between the
components can occur. These services, which are available to all components, come in the
form of a set of API functions.
COM promotes the use of component-based development
Before the advent of component-based development, the predominant technique was
procedure-based development. This style is linear in nature, and programs written using it
start at the first line of code, and finish either when the last line is executed, or an
Exit statement is reached. Applications written in this fashion tended not to be very
adaptive to what was happening around them.
In Visual Basic today, it is quite easy to reference (that is, to plug in) a library of
functionality. Where we used to have to write complex API calls to talk to a database, we
now simply have to set a reference to the appropriate library of functionality (as in the
following figure) to be able to use it in our own programs. In this particular instance,
we're creating a reference in our Visual Basic project to a COM-based library that will
allow us to communicate with a database:
Component-based development also allows the programmer to take advantage of using
pre-packaged components or tools. An example would be if you were writing a communications
program that dealt with receiving and sending information over a modem. You could go out
and buy (fairly inexpensively) a package that would handle the communications
functionality for you, ridding yourself of the need to write large amounts of code to see
if a port was open. You would just have to reference the library, and write a small amount
of your own code. These libraries may be thought of as black boxes: you don't need to
concern yourself with how they work; you just know that they do work.
COM promotes object-oriented programming
COM (and component-oriented design in general) was created with object-oriented
programming in mind. This is a methodology that promotes thinking about software 'objects'
and the way those objects interact with each other, rather than their implementation.
Although this isn't a book on OOP, it is very difficult to discuss COM programming without
covering many aspects of object-oriented programming. Therefore, from time to time we will
be discussing further some of the aspects of object-oriented programming.
In order better to understand what COM is useful for, and why it works the way it does,
it's revealing to delve into the genesis of COM and trace how it has evolved into its
present form. There are two technologies that we can identify as the springboard for COM:
OLE and DDE. OLE (later called OLE 1.0) is short for Object Linking and Embedding,
which in its original form was a technology that tried to solve the problem of compound
A compound document contains data of several different formats. To help you picture
what I mean, think about a word processing document such as a status report. It's probable
that you would want to include some calculations from a spreadsheet in a document like
this, and maybe a pie chart as well. Before OLE, even if you were somehow able to put the
information into the document, there was no standard technique for automatically updating
the document when figures in the spreadsheet changed, or for changing the pie chart to a
bar chart, for example.
OLE 1.0 provided a solution for this problem by enabling you to take your spreadsheet
and place it directly into a word processor document, as in the figure below. Changes to
the spreadsheet are automatically and immediately reflected in the document, edits to the
embedded spreadsheet can be made through the document simply by double clicking on it, and
all the data in the document can be stored together in a single file.
This was a great piece of technology, but it was rather ahead of its time in terms of
the hardware that was available to support it. Working with OLE 1.0 required quite a bit
of memory and CPU time, but it did get the minds at Microsoft thinking about the best way
of getting software components to interact with one another, and in as efficient a manner
Before even OLE 1.0, a little gremlin called Dynamic Data Exchange (DDE) was being used
to allow pieces of software to interact with each other. It allowed data to be transferred
between two applications, and also made it possible for one application to be notified
when data in another changed. However, DDE didn't catch on - not only did it suffer from
poor performance, but also it was difficult to use, and quite easy for the link between
the two applications to break. Even today though, you can still find information about DDE
in the Visual Basic help files.
Microsoft decided to make a second stab at component interaction in the early part of
1993, at which time OLE 2.0 came into existence. COM was a core component of OLE 2.0, and
so the latter can be used as a way of explaining the features we know COM to have today.
By providing COM as a means for components to communicate with one another, OLE 2.0 went
well beyond the linking and embedding used to create compound documents. In response,
Microsoft's marketing department came to the decision to drop the name "Object
Linking and Embedding" and simple call it "OLE" (most people pronounce it
"oh-lay"). OLE was the rubber stamp applied to anything that dealt with COM
One of the products of this expansion was OLE Automation. Put simply, OLE Automation
(which today is just called Automation) allows a client to call the services exposed by a
suitably endowed server, which is usually a major application. For example, it's possible
using this technology to create an instance of Microsoft Excel, put numbers into a new
workbook, crunch the numbers and then close the application again all from a Visual Basic
program, without a single line of Microsoft Excel VBA code! Indeed, many software
companies make their living from programming Automation clients that work with the
Microsoft Office suite of applications.
If you've come across VBXs in your Visual Basic career, you're probably thinking that
they must fit in to the story at around this point - aren't they reusable software
components that you can use in Visual Basic? Well, you're on the right road, but you're
headed in the wrong direction! VBXs were pre-packaged components written to tie into
Visual Basic specifically, providing services such as list boxes or communication
controls. These VBXs were great at the time because they provided support for the
development methodology called Rapid Application Development (RAD). Just like the example
in the last section, if you needed to have communication functionality in your program, it
was as simple as dragging a control from the toolbox onto a Visual Basic form.
Although VBXs had the achievement of spawning a third-party industry that provided
pre-packaged developer tools for the Visual Basic programmer, they also had three
significant problems. First, they were not COM-based and were therefore a proprietary
technology for Visual Basic - there was no way to use them from other programming
languages. Second, you couldn't actually build a VBX using Visual Basic - instead you had
to use something like C++, and even then they were difficult to write. Third, VBXs were
limited to a 16-bit architecture.
According to Microsoft's web site, "COM supports the only currently viable
component marketplace. The market for third-party components based on COM has been
estimated at US$670 million in 1998, with a projected 65 percent compound annual growth
rate, growing to approximately US$3 billion by 2001. (Source: Giga Information
It's great to know there are thousands of companies out there right now building
components to make our lives easier!
In response to the Internet storming the beaches of computing, Microsoft marketing went
into an elevated state of naming in the early part 1996 and decided that their Internet
technologies would fall under the name ActiveX. At the same time, Microsoft came out with
a new specification for OLE controls, otherwise known as OCXs (because the files
containing them have the extension .ocx). These replaced VBXs: they were based upon COM
technology, and they were easier to create, too. In fact, creating them was made even
easier when Microsoft allowed Visual Basic developers to create their own controls with
Visual Basic 5. A final name change gave OLE controls the title by which we know them
today: ActiveX controls.
The reason for "ActiveX" being added to the name harks back to the first part
of the previous paragraph. Microsoft enabled Internet surfers who were using their
Internet Explorer browser to view web pages that had OLE controls embedded in them, but
because OLE controls had suddenly become a part of the Internet strategy, their name had
to change! ActiveX controls were designed to be very functional and fast, as well as
lightweight in terms of size compared to their VBX precursors, since (as now) bandwidth
was at a premium.
With Visual Basic, it's now possible to create ActiveX controls, ActiveX DLLs and
ActiveX EXEs. ActiveX DLLs and ActiveX EXEs are similar to ActiveX controls, but they do
not have the user interface attached to them that one would normally associate with
ActiveX controls. In fact, the DLLs and EXEs are more typical of the COM-enabled software
components that we will be writing in this book, and we will of course be discussing them
further in forthcoming chapters.
COM technologies allow developers to deal with a myriad of problems that traditional
software development simply could not handle. In this section, we'll address these issues
and talk about the real-world problems that can be solved with COM-enabled technologies.
The Problem with Software
Software reuse is the goal that everyone's trying to reach, but no one ever seems quite
able to get to. Much software development, especially that of a few years ago, does not
support effective code reuse. You may have your routines sitting around in .bas files or
text files somewhere on the hard drive or the network, but even finding them can be
difficult if you don't have a centralized location for them, and they usually contain code
that is specific to the last project you worked on. In response to this, most developers
resign themselves to the cut-and-paste method of development: find the pieces you want,
paste them into the program, and debug them.
Another software development problem pertains to dynamic-link libraries. These are
usually files with a .dll extension that hold pieces of code that can be accessed by
another program dynamically, at runtime. Unfortunately, it's not always easy to make calls
to the library, and plenty of time can be wasted just in debugging your application's
connection to it. (What? It wanted a string instead of an integer? Oh, that's why I'm
getting the blue screen of death!) Also, if and when the library is updated, it's all too
easy to break the compatibility between the new library and applications written to use
the old version. If it turns out that you need two versions of the library on the same
system, this can cause significant problems for your applications.
Software components written for one language do not always work within another
language. Could I take my .cls files, stick them into a Visual C++ project and expect them
to work? Of course not - a .cls file would just look like a bunch of text. What's needed
is a solution that will allow you to create software components in one language that can
be used in multiple languages. Wouldn't it be great to be able to create a component in
Visual Basic that could be used in Visual C++, Visual InterDev, Delphi, and Internet
In general, legacy applications do not expose a way to allow developers to use their
resources programmatically from another application. For example, let us say that we have
an application that is good at presenting data and another that is good at creating
graphs. It would be nice for the presentation application developer to be able to use the
resources of the graph application for their own application rather than have to develop
their own graph engine.
Lastly, traditional applications are unable to exploit components that are located on
another networked machine. You may have a component that is good at crunching numbers or
can provide database services better on a separate machine than putting all the libraries
onto the client machine. If only there were a way of creating applications whose separate
pieces run on different machines, so that the most appropriate set of resources could be
chosen for each part. How good would that be?
It's about time we began to consider how COM solves these issues and provides this kind
of functionality for us. The beauty of using Visual Basic and COM together is the
combination of the two makes it quite easy to address the problems without too much effort
on the part of the developer - Visual Basic does most of the hard work for you!
COM-based components promote software reuse. COM components are usually written to be
generic, which allows them to be used in a multitude of ways by different pieces of
software. A graphing component, for example, could be COM-enabled so that you could use it
in whatever container you choose. You may want to put a graph in your Microsoft Word
document, or you might want to put it on a Microsoft Access form. The great thing is that
you can use it in either application, and it will work the same way in one as it does in
Looking at the pair of screenshots below, you can see that the Microsoft Chart
Component looks and acts the same in both applications. This is very productive because if
a developer knows how the chart control works for one application, they are likely to know
how to make it work in another application.
As to the problem of being able to find your components after you've written them, COM
has a solution that deals with this and more. Every time that you create a COM component
with Visual Basic, an entry is placed in the system registry that indicates exactly where
on the computer is the file containing your component. In fact, COM goes further than
this: it requires that in order for a component to be used, an entry for it must exist in
the registry. Without such an entry, the COM runtime will be unable to find the component
when it is asked to do so.
This theme will be developed in the next chapter, along with a more complete
description of how the registry works.
COM components are language independent. COM components can not only be used in Visual
Basic, but also written in Visual Basic. More importantly, you can take a COM component
you created in Visual Basic and integrate it into your Visual C++ or Visual J++ project.
Although you can't create COM components in Visual InterDev, you can certainly use them by
calling them from Active Server Pages. At the moment, language independence is typically
limited to the programming languages Microsoft supports, but this is changing as the
momentum for COM continues to grow.
COM objects have object-oriented features: obeying the strictures of encapsulation,
they are accessed using only public methods and properties, so that any data they contain
is hidden from public consumption. However, object-oriented programming is a tool of this
book rather than its subject matter, so I'll limit any further discussion of it until it
is relevant to the matter at hand. I suggest reading Beginning Visual Basic 6 Objects by
Peter Wright (Wrox Press) as a good primer in creating and using software objects.
Time for me to get on my soapbox. If you haven't been to a Usenet newsgroup with
"oop" (short for Object-Oriented Programming) in its name, you may not know that
there seems to be something of a Jihad over OOP. The purists will tell you that all the
software you write must adhere to the concepts of object-oriented programming.
For my part, I like to invoke the old saying, "When your only tool is a hammer,
everything looks like a nail." I am not against OOP; indeed, I am quite happy that
Visual Basic uses classes and encapsulation - it has made it simpler to develop
applications, and it makes debugging much easier. I do think, though, that Microsoft is
beginning to push the envelope (yet again) and reappraise the argument that says you
should use object-oriented development just because you are supposed to. I am sure to get
flame mail on this one, but I think it is better for the developer to decide how they want
to design their programs based on what their users require, rather than on an ideological
Another great feature of COM is called DCOM, or Distributed COM. This was first shipped
with Windows NT4, and was released as an add-on for Windows 95 in late 1996. It also ships
as standard with Windows 98. DCOM allows your applications to call upon components that
may not even be on the same machine as they are. DCOM takes the notion of location
independence that's supported by COM's use of the registry to store the locations of
components (provided that there's an entry, it doesn't matter exactly where the component
is) and extends it to the network. Furthermore, it provides security for components that
are distributed in this way. I will go into more detail on this subject in the DCOM
You should be able to see from this discussion that there are a number of advantages to
using COM and DCOM as platforms for building and using components. COM goes out of its way
to provide a robust and powerful environment for your software development needs.
To reinforce the point, let's take a look at a problem for which COM could provide a
viable solution. Phil is the project leader of a new application for his company Frogs
& Turtles, a retail chain that sells garden plants and accessories. Currently, they
are using proprietary software that runs at each retail chain and on each order taker's
system at the catalog telephone center. This application batches all orders into a text
file and uses a modem to transfer the orders for the next day overnight, where they are
then updated to the main database. If there are orders for something that's not in stock,
a fax is sent to the representative that took the order the next morning. Unfortunately,
there are some problems with the current system.
The first problem is that the software is proprietary, so Phil and his group of
developers are unable to add any features to it or debug any of the problems they have
found without having the code base. Second, customer satisfaction is low due to inventory
control problems. Because they have grown so quickly, their technology has not kept up
with their demand: they cannot tell what their inventory levels are until the nightly
batches are through. In addition, when a customer puts in an order late in the day, they
will not know until the representative calls the next morning that their order is on
backorder. Third, when orders are filled out wrongly and entered into the system, it can
mess up reporting, wreck the order, or even crash the system the order took place on.
Phil's bosses asked him to develop a system that would solve their growing problems. As
always, they gave him two months to complete a project that needed six. (Bosses putting
ambiguous, over-ambitious deadlines on a developer? Never heard of that!) In addition, his
bosses asked if the Internet could be used as the means of communication between the
retail stores and the telephone center. In response, Phil decided to research COM and see
how it could be used with Visual Basic (since most of his developers were Visual Basic
programmers). He concluded that he would implement COM-based techniques to solve their
problems. Throughout the rest of the book, I will demonstrate some of the techniques Phil
used to develop his solutions.
By now, you should have an idea of what COM is and what it can do for you, so it's time
to wheel out the big guns. Microsoft Visual Basic can make a developer very productive
when it comes to creating and using COM components. In fact, Visual Basic itself relies
very heavily on COM technologies.
One of the advantages of using Visual Basic to create COM components is the ease with
which it can be done. Visual Basic hides a lot of the plumbing needed to implement COM
components and lets you focus on developing what your components will do, or what business
functionality they will address.
The Visual Basic COM Players
Microsoft Visual Basic allows you to create a number of different COM-enabled projects,
three of which we will be concentrating on in this book. First, there are ActiveX
controls, which have a user interface associated with them. As a Visual Basic developer,
you are probably most familiar with the ActiveX controls that are available as tools in
Also, if you go to Visual Basic's Project menu and select Components... (or just use
Ctrl-T), you can see all the ActiveX controls that are registered on your local machine
(that is, those that have entries in the system registry):
ActiveX controls generally have a .ocx file extension, as you can see if you look at
the Location field in the previous screenshot.
The second kind of project we'll be looking at is the ActiveX DLL. These are
COM-enabled files with a .dll extension, and they contain the COM components that you will
find yourself using most often. Unlike their ActiveX control counterparts, components in
ActiveX DLLs typically do not have user interfaces. Generally, they are made up of a class
or a set of classes that are blueprints for the COM objects that you will create.
Thirdly, ActiveX EXEs are very similar to the ActiveX DLLs, except they are
out-of-process servers, which means that they don't run in the same memory space as the
application that calls them. By the same reasoning, ActiveX DLLs are often called
in-process servers, because they do run in the same memory space as the application that
calls them. Don't worry if some of these terms are unfamiliar to you at the moment; just
understand that there is a difference, and I will have plenty to say about the advantages
and disadvantages of in- and out-of-process servers later in the book.
Individually and collectively, these three different project types allow us to easily
create reusable components with Visual Basic. Moreover, because these ActiveX components
are built on COM we can use them with COM components irrelevant of language or container.
In Chapter 5, we'll create a simple ActiveX control consisting of two text boxes that
our developer, Phil, might want use in his application. In Chapter 6, we'll look at how he
can distribute COM objects across a network and we'll see the importance of ActiveX EXEs
in achieving this. Finally, in Chapter 7 we'll see how Phil can easily provide multi-user
support for his ActiveX DLLs.
You will notice that this chapter is short relative to the rest of the chapters in the
book. This is because I wanted to provide you a quick primer of what COM is. If you
stopped reading this book right now (which you shouldn't), you would at least know what
COM is and what it can do for your development.
Specifically, we discussed the concepts behind COM and how we could define it. There
are many parts to COM, and it provides us with many services and considerable
functionality to solve software problems.
Next, we delved into the history of COM, from its humble roots in OLE 1.0 to its role
in Microsoft's Internet strategy. This history helps us to establish how COM came into
being and developed into what it is today.
Lastly, we discussed the problems with typical software development and how COM
actually helps us to solve these problems. Also, I explained a real-world programming
scenario in which the use of COM might be helpful, and we will spend some time in future
chapters using COM technologies to solve the not-so-unique problems we uncovered.
At the beginning of the chapter, I mentioned that we were on a journey. At this point,
we have made a few steps down the path. Strap your boots on, because we are now heading up