Click here to Skip to main content
15,884,425 members
Articles / Desktop Programming / ATL
Article

Connecting more than one COM client to a desired object

Rate me:
Please Sign up or sign in to vote.
4.35/5 (12 votes)
30 Jul 20032 min read 67.4K   1.2K   36   8
How to connect more than one COM client to a desired object by using monikers to bind to running objects

Introduction

There are situations when the server application creates a pool of objects, and the client has the possibility to bind to one specific object. If the pool size is one, than the server can create a singleton instance and all the clients will connect to the same object. In the case of a pool bigger than one object, a solution could be the use of monikers. My solution proposes the change of the class factory for an ATL project. The new class factory will manage the name space by creating a strong table to store references to running objects. Strong table means, that when the last client releases the object, the object is still running, expecting new clients. To shutdown the object, the application must specifically remove the object from the table. In a multithread environment at least two racing condition can appear:

  • Two threads will try to create an object with the same name
  • One thread tries to connect to an object, while another thread removes it from the table

To avoid this, the server application register itself into a STA by calling CoInitialize(NULL). In this situation the access to the table is serialized.

To use the new factory class DECLARE_CLASSFACTORY_EX(CComClassFactoryMon) macro should be added to the header file:

class ATL_NO_VTABLE CTheObject : 
... 
... 
{ 
public: 
... 
//here it is set the class factory for the object 
DECLARE_CLASSFACTORY_EX(CComClassFactoryMon) 

Details of usage

The server component has one interface ITheObject, and the interface has one method -

HRESULT TheObjectID([out,retval]LONG* plID); 

The implementation class has a static member variable m_lCounter; The constructor increments m_lCounter and caches it. The TheObjectID method returns the cached value of m_lCounter, and in this way every component has a 'unique' identifier (of course if m_lCounter rolls over the uniqueness is compromised).

A client interested in a specific object will call:

HRESULT hr = CoGetObject(
  OLESTR("clsid:4F408B03-404A-4E14-949F-686969AE21D8:!myObject"),
  NULL, __uuidof(ITheObject), (void**)&spITheObjectPtr);

If the "myObject" is not already running, the class factory will create it an insert it in the table.

A client who does not care which object will get, can call:

HRESULT hr = ::CoCreateInstance(CLSID_TheObject, NULL, 
  CLSCTX_ALL, __uuidof(ITheObject),(void**)&spITheObjectPtr);

When you decide that you do not need the object anymore you must call:

HRESULT hr = CoGetObject(
  OLESTR("clsid:4F408B03-404A-4E14-949F-686969AE21D8:"),NULL,
  __uuidof(ITheObjectsTable),(void**)&spITheObjectsTable);
if(SUCCEEDED(hr))
{
  spITheObjectsTable->RemoveObject(OLESTR("myObject"));
}

There are two projects:

  • MonikerServer ATL project
  • MonikerClient MFC project

If you compile the MonikerServer project on your computer, the server will register itself. If you choose not to compile the project, then run /Release/MonikerServer.exe to allow the server to self-register. Start the MonikerClient application and enter a name into the edit box. Click connect, and the readonly text box will display the object ID. Start a second MonikerClient instance, enter the same name and you should get the same ID. Select the checkbox "On close remove the object from the table" and click OK. Click OK in the other MonikerClient instance. Now all the clients are gone, the object is removed from the table and the MonikerServer application will shutdown itself.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionConnecting more than one COM client to one .dll component Pin
netman_par3-Apr-07 20:11
netman_par3-Apr-07 20:11 
AnswerOne solution one question Pin
__Egon__10-Apr-07 17:36
__Egon__10-Apr-07 17:36 
AnswerRe: One solution one question Pin
netman_par11-Apr-07 20:47
netman_par11-Apr-07 20:47 
Questionload the unique component in service Pin
netman_par16-Apr-07 20:27
netman_par16-Apr-07 20:27 
GeneralGood work Pin
Balkrishna Talele20-Apr-04 21:17
Balkrishna Talele20-Apr-04 21:17 
GeneralDispEventAdvice Pin
Balkrishna Talele28-Mar-04 17:45
Balkrishna Talele28-Mar-04 17:45 
GeneralMy server is starting again while connecting. Pin
6-Nov-03 23:38
suss6-Nov-03 23:38 
GeneralIt works. Pin
Schaudin10-Nov-03 22:22
Schaudin10-Nov-03 22:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.