Link to home
Start Free TrialLog in
Avatar of rosborn051498
rosborn051498

asked on

Limit ActiveX to single instance

I wrote an ActiveX control that reads/writes to a COM port and updates global variables based on information received over port.  Since there is only one COM port, I want multiple applications to be able to use a single instance of the control (which "owns" the COM port).  Teh control updates its variables and multiple calling apps can read the properties from the same instance of the control.

How do I do this?

Avatar of galkin
galkin

What you can do is add code to register your control into OLE Running object Table when first instance is created. when the second instance is about to be created it looks up into ROT and if it finds moniker associated with control it extracts first instance interface pointer and paases it back to client instead of its own. I guess if your control doesn't have visual implementation the better way is to implement it as out of process server then inproc ActiveX control
Avatar of rosborn051498

ASKER

I'm not yet familiar with monikers, do MFC-generated ActiveX controls support the IMoniker interface?  How is the interface pointer passed back?  In short, do you have sample code?

Can you please elaborate on the "out of process server then inproc ActiveX control"?  I hope I don't have to be out of process, as this may cause a substantial preformance hit.  Right?  By the way, I am not yet thread safe.  I imagine this would be fairly important for an out of process server.

Thanks, this is great help.
No MFC doesn't generate Moniker but you can avoid using this. Use OLE global wrappers RegisterActiveObject, GetActiveObject and RevokeActiveObject.
I still advise you implementing it as out of process server. MFC provides excellent support for it. If you are going to implement it as DLL you may face a problem when application that loaded this DLL into memory exits, it automatically unloads DLL. Out of proces(or local server) is EXE. You can generate this server by creting AppWizard project and checking server check box. You can always make server main window invisible to hide its UI.  
This may be a dumb question, but can an ActiveX control (OCX) be an out of process server?  I want to encapsulate my functionality in an OCX so Visual C++/Visual Basic programmers can easily use it.
Out of process controls are possible, but are impractical because of the very serious performance penalties the out-of-proc marshalling causes.

.B ekiM
Actually ActiveX control in new Microsoft implementation must implement IUnknown four OLE exported functions and other functionality as needed. The problem is what to name ActiveX control. I have never heard of out of process ActiveX controls. Recently it was not possible since ActiveX(OLE that time) control must have implemented IViewObject interface that is not marshalled across process boundaries. Not requirements to ActiveX control have been dropped down so minimal out of process server can be referred to as ActiveX control also.
Your help has definitely pointed me in the right direction, but I still don't know exactly how to do it.  

Nice to hear from you, Mike.  I just saw you at the VCDJ in Boston.  The penalty of marshalling was discussed frequently there.

Let me just add (or reiterate) a few things:
       * the control has no UI at run-time
       * the control talks to a proprietary device on a COM port
         and must alert all container apps (via events) when
         a property changes
       * containers can get/set properties, which are
         global to all containers.  When one container changes
         a property, the others must be made aware of the
         change.
       * all containers will be on the same machine

Registering in the ROT seems easy, but I'm not sure how to pass back an interface pointer.  Also, would I have to write code to keep track of how many containers are using me?  Would I need to fire individual events to each container?  Would get/set methods be thread safe?

Automation server is sounding like the way to go.  All references I have seen to Automation Servers have been "*.EXE"s.  Does that mean that in order to provide an out-of-process server that I must create an executable that uses my ActiveX control, and that also exposes an interface, which could include a way to call the control's properties directly?

By making it an automation server, I seem lose some of the "traditional" ActiveX control features, such as easy integration into Visual C++/Visual Basic apps.  We don't specific plans to distribute the control for developers, but I don't want to make the process difficult for our other in-house developers.  What to do, what to do?


The only one problem that prevents you from designing inproc server is that you must control only one instance of your object and module where this object resides must be alive until all all its clients are connected to it. This leads to conclusion that out of proc server(EXE) is the only solution despite all desadvantages it has over inproc server.
Concerning getting pointer to existing instance of the object more correctly that each client before trying to create a new instance of the object server would check with GetActiveObject if such an instance is already running and if so would try to connect to the running one. But if you do not have control over all client which are supposed to use you object you can do what I suggested. Namely when new instance is created it fitst checks in ROT and if it finds running instance it extracts its pointer and passes its to the client instaed of its own Then it terminates itself(since it is EXE).
You can implement IDispatch interface. In this case you can add properties and methods and no marshaling is needed since OLE itself provides marshaling for IDispatch interface. Since OLE implements local/remote transparency client doesn't care if your object is inproc or local.
Thanks.  I missed notification of your last comment, so haven't responded sooner.  Sounds like out-of-proc server is the way to go.  Your last comment is helpful, but I'm still a little confused about how to do it.  Do I create an EXE that uses my control, then design a custom interface for clients to use?  Or is there a way to pass the control's interfaces directly to clients?  I have control over what all clients do, since (for now) they are all in-house.  Basically, I need a little more high-level help for writing an automation server that resembles a "traditional" ActiveX control.  Such as, how do I fire events to all clients?  
You can create skeleton out of process server using AppWizard. When stepping through the wizard and aked what type of compound document you would like to support choose either mini server or full server. Mini server cannot run stand alone just serve othe clients. Full server can. There is one MFC sample demonstrating using connection points in MFC out of process server. Serach microsoft knowledge base.
I will search the KBase.  I believe your answers lead me in the right direction, but have not directly answered my questions.  While I do appreciate your help, I don't think I got a complete answer.  

I'm sorry if I have have a bad attitude.  I'm sure you are more than capable of helping me, but I just don't think you've provided the answers I expected.

I guess I'll research automation servers and try to find the KBase example.  I still don't know for sure what the architecture looks like (do I write an auto server EXE that uses my control?  How do I fire events to multiple clients? etc.)



ASKER CERTIFIED SOLUTION
Avatar of galkin
galkin

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks for your help.  I will research as suggested.  I was hoping to use my control, since it has already been written and tested.  Maybe I can port some of the code over.