Microsoft Corporation
September 1999
Summary: Provides a description of COM+ Events. (7 printed pages)
Notifying interested parties that there have been changes to information is a fundamental issue of distributed computing. In the past, subscribers were provided with an interface on which a method call could periodically be called to determine if changes had taken place. Such a procedure is known as polling the publisher. While polling is a simple way to obtain the required information, there are some disadvantages to using this method. Polling wastes time for both the publisher and subscriber. The subscriber must send a method call to the publisher and the publisher must relay an answer to the subscriber—even if there have been no changes in the information. Polling also involves a time lag between when the information actually changed and when the subscriber polls for it.
Ideally, an events system should provide a way to initiate the notification of interested parties when information changes. In a tightly coupled event (TCE), the publisher is provided with an interface on which to call a method when a change occurs. COM Connection Points are an example of a TCE system. The subscriber in a TCE system knows which publisher to request notification from and the interfaces that are exposed. A TCE system requires both the publisher and subscriber to be running at all times. Additionally, the mechanism used to connect the callback interface must be known in advance, and these mechanisms can be widely divergent. TCEs also provide no way to filter or intercept an event. (Filtering is a way to designate event notification only when certain changes occur or when certain values are reached. For example, you may want to know about your favorite stock only when it reaches a predetermined price.)
COM+ Events is a loosely coupled events (LCE) system that stores event information from different publishers in an event store in the COM+ catalog. Subscribers query this store and select the events that they want information about. Selecting event information from the event store creates a subscription. When an event occurs, the event system checks this database to find the interested subscribers, creates a new object of each interested class, and calls a method on that object.
The steps for implementing COM+ Events in Visual Basic® 6.0 are short and simple.
This is a standard Visual Basic ActiveX® DLL with the following attributes:
There should be no other code in this module.
Example:
DLL Name is My_Events, Class Name is Account
Public Sub LoginSuccessful(ByVal Email As String, _ ByVal FullName As String,
ByVal AccountID As Long)
End Sub
This is also a standard Visual Basic ActiveX DLL with the following attributes:
Create Private Sub() methods that correspond to each of the Public Sub() methods in the event class DLL, preceding the name of the Sub() with the name of the interface and an underscore.
Example:
Implements My_Events.Account
Private Sub Account_LoginSuccessful(ByVal Email As String, _ ByVal FullName As
String, ByVal AccountID As Long)
‘Code to do something based on event goes here
End Sub
Wizards in the COM+ Explorer will walk you through each of the above steps.
To publish an event, simply call CreateObject() on the event class DLL you previously created and then call the appropriate method to publish the event.
Example:
Dim objEventClass As Object
Set objEventClass = CreateObject(“My_Events.Account”)
objEventClass.LoginSuccessful(“KingDaddy@Hotmail.com, “, _”Elvis is the King”,100000)
Set objEventClass = Nothing
The steps for implementing COM+ Events in Visual C++® 6.0 are short and simple.
This simple COM object defines the event interface and event handler method prototypes (there should be no implementation in this object).
Example:
// EventClass.idl
//////////////////////////////////////////////////////
// ISystemEvents Interface
[
uuid(6DBAC91E-D1E2-11d2-9A34-00C04F72EB9B),
helpstring(“ISystemEvents Interface”),
oleautomation,
pointer_default(unique)
]
interface ISystemEvents : IUnknown
{
[helpstring(“method ProcessCreated”)] HRESULT
ProcessCreated(BSTR szProcessName);
[helpstring(“method ProcessTerminated”)] HRESULT
ProcessTerminated(BSTR szProcessName);
}
// Event Sub(scriber) Class
[
uuid(992FE540-D1E3-11D2-9A34-00C04F72EB9B),
helpstring(“EventSubClass Class”)
]
coclass EventSubClass
{
interface ISystemEvents;
};
// EventClass.h : Declaration of the CEventClass Class
/////////////////////////////////////////////////////////////////
// CEventClass
class ATL_NO_VTABLE CEventClass :
public CComObjectRootEx,
public CComCoClass
{
public:
CEventClass()
{
}
public:
};
This is also a standard Visual C++ COM object with the following attributes:
Example:
// EventSubImpl.h : Declaration of the CEventSubImpl
//////////////////////////////////////////////////////////////////////
// CEventSubImpl
class ATL_NO_VTABLE CEventSubImpl :
public CComObjectRootEx,
public CComCoClass,
public IDispatchImpl<&LIBID_EventSUBSCRIBERLib>,
public ISystemEvents
{
public:
CEventSubImpl()
{
}
BEGIN_COM_MAP(CEventSubImpl)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ISystemEvents)
END_COM_MAP()
public:
// ISystemEvents methods
STDMETHOD (ProcessCreated)(BSTR);
STDMETHOD (ProcessTerminated)(BSTR);
};
// Subscriber implements methods to handle the captured
// ISystemEvents events.
// EventSubImpl.cpp : Impl of CEventSubImpl
/////////////////////////////////////////////////////////////
// CEventSubImpl
STDMETHODIMP CEventSubImpl::ProcessCreated(BSTR bstr)
{
return CommonMethod(_T(“ProcessCreated”),bstr);
}
STDMETHODIMP CEventSubImpl::ProcessTerminated(BSTR bstr)
{
return CommonMethod(_T(“ProcessTerminated”),bstr);
}
Wizards in the COM+ Explorer will walk you through each of the above steps.
To publish an event, create the event class object (also accomplished using ISystemEvents) and then call the appropriate event handler method (ProcessCreated or ProcessTerminated—implemented by the subscriber) to fire the event.
Example:
LRESULT CFoo::FireSystemMethod(IUnknown* punk, BSTR bstrval,
int i)
{
ISystemEvents *psystem =0;
HRESULT hr = punk->
QueryInterface(__uuidof(ISystemEvents), (void**)&psystem);
exit(hr);
switch(i)
{
case 0: // ProcessCreated
// Event firing happens here
hr = psystem->ProcessCreated(bstrval);
break;
case 1: // ProcessTerminated
// Event firing happens here
hr = psystem->ProcessTerminated(bstrval);
break;
exit:
RELEASE(psystem);
return hr;
}
COM+ Events matches and connects publishers and subscribers. An event is a single method in a COM+ interface, originated by a publisher and dispatched to the correct subscriber or subscribers. A publisher makes the method call to initiate an event and a subscriber receives these calls from the publisher. COM+ Events maintains the list of interested subscribers who will receive the calls and directs those calls without requiring the knowledge of the publisher.
The connection between publisher and subscriber(s) is known as an EventClass. An EventClass is a COM+ component that declares the interface used by a publisher to fire events. The subscriber must implement these interfaces in order to receive events. To do so, specify the interfaces and methods you want an EventClass to contain by providing a type library (using Visual Basic), or by inheriting from the appropriate interfaces (such as Visual C++). EventClasses are stored in the COM+ event store (COM+ catalog), by publishers using either the COM+ Administrative SDK functions or the Component Services administration tool.
To register an event in the event system, a publisher creates one or more EventClasses. This EventClass indicates the events that can occur and, optionally, identifies the publisher. Then the publisher instantiates the EventClass by calling CoCreateInstance or CreateObject and requesting the event interface be returned. The instantiated EventClass object contains the event system’s implementation of the requested interface. By invoking the appropriate method through the event interface, the publisher automatically fires an event on the EventClass object. COM+ Events searches the subscription database (COM+ catalog) to find all the subscribers who have registered subscriptions to that interface and method. It connects to those subscribers (by direct creation, monikers, or queued components) and calls the method. To support more than one subscriber notification for an event, methods can contain only input parameters and must return only success or failure HRESULTs.
The following diagram depicts the COM+ Events architecture.
Figure 1. COM+ Events architecture