tags:

views:

891

answers:

2

I'm planning on making my existing application into an RTD server.

The application is currently written in C++ and while I will eventually port it to C#/Mono I want to be able to add the RTD functionality with C++.

I have found a few sample pieces of code (the MSVCRTDServer) and this site: http://weblogs.asp.net/kennykerr/archive/2008/10/29/excel-rtd-server-in-c.aspx

Unfortunately these are DLLs and I have forgotten all I knew of COM (good riddance) a long time ago.

How do i go about incorporating the DLL examples into the EXE? This is apparently about packaging the COM server in an EXE rather than a DLL.

EDIT:

Note, the existing app has an MFC GUI.

EDIT:

The intended use is taht the existing GUI app will be running - no need for clients of the COM/RTD interface to launch the app. (Although I won't deny that would be nice)

Basically i want to implement the IRTDServer interface with my own data - so that Excel (or other apps) can access the dynamic data that the application provides. (It is a program that talks to a serial port device - that device has status/state that changes and i want to be able to update clients on the changes asynchronously)

So, I need to create a COM object and register it so that clients can "see" it.

I am not sure how to add a COM object to an exe and have that COM object implement an existing/pre-definfed interface.

EDIT I started a bounty on this so I could get code samples. Apparently I am too lazy and stupid (or maybe it is just the hyper aversion to COM) to get started with existing answer by Franci Penov. (which is very useful and a great start)

So basically what I am looking for is:

code to take my existing dialog based MFC application that has a bunch of threads running and turn it into an RTD server (that has the same UI)

All that cocreate and CoThisandthat, etc. Where do I put that code in my exe? How do I extend/implement the IRTD stuff?

A before and after of a sample MFC hello world app (dialog based) is going to get the accepted answer.

  1. Before app with all the source code for mfc dialog app.
  2. "after" app that is based on the MFC app in step #1 that implements the RTD srver interface and all of its source. (all project files, source, etc)
  3. steps taken in the GUI/visual studio and otherwise to create step 2 from step 1. ( IDL, etc other files created. )

Ideally this is provided for VS2008, but any version would work.

Thanks.

+2  A: 

EDIT: Dude, I have not touched MFC since year 2000. I was hoping to stay that way for the rest of my life. :-) Anyway...

Aparently, the wizards have evolved since last century. The following steps for adding ATL COM support to and MFC app are for VS 2008.

  1. Generate a simple MFC dialog based app called MFCTest. Do NOT check the Automation checkbox in the wizard.
  2. Right click on the project and select Add / Class... In the dialog, choose ATL Simple Object. You will get a warning that ATL support will be added to the project.
  3. A new wizard will open with options for the new ATL object.

You should be done.

Frankly, I don't see any reason to post here a wizard-generated code. But if you have further questions on particular pieces of that code, post them on SO and I'll help you.


EDIT: This is slowly turning into an article. If we go on like this, I might even publish a book. :-)

Once you have the simple ATL object integrated in the MFC project, you can add the RTD interface to it. You will need to both inherit from the interface and add it to the COM_INTERFACE_MAP. Since the RTD interface is an IDispatch interface, you will have to inherit your class from IDispatchImpl<> and to add IDispatch to the COM_INTERFACE_MAP using COM_INTERFACE_ENTRY2 (in order to specify that it's implemented through the IRtdServer.

I am not really familiar with how RTD works. You might also have to add support for COM connection points to your class, if Excel needs to supscribe to your updates. Here's also a link to refresh your connection points in ATL knowledge.

Btw, I stumbled upon this blog post that has the C++ definitions of the two RTD interfaces. You probably already have them, but I thought I'd add it for completeness sake.


The easiest way would be to create new ATL EXE project through the VS wizard and let it take of the registration and the process management part. The rest is not that different.

If you need a particular sample to jumpstart your journey back to the land of COM out-of-proc, you can look at LABRADOR.

Couple of links that might be of further interest to you:

EDIT: If you just need to know how to register an object in your EXE with COM, so client apps can CocreateInstance it, check out CoRegisterClassObject. However:

  • the object needs to be a COM object
  • you need to implement a class factory for it
  • if you want process management (ie, COM starts your app on demand), the ClassID nees to be registered in the registry
  • if the client is going to create it through ProgID, the ProgID needs to be registered in the registry
  • you might need a custom proxy/stub dll, if you are doing custom marshalling
  • if your app has UI, you will have to modify the shutdown logic, so that when the user closes the UI, the app does not exit untili the last COM reference to your objects has been released as well

EDIT 2: I'd still suggest you look at the ATL out-of-proc sample and at the skeleton the ATL wizard would generate to understand the sequence of operations. However, you might need to delve a bit in the ATL code to see what exactly is going on.

Here's the short version of the process:

On a startup, the application nees to check for a particular command line argument - /embedded. If that argument is present, it means the app is being launched by COm in response to a CoCO call. The app might choose to not show its UI at this point.

Whether the app shows the UI or not, it has to register the class factories for any COM objects it provides through the CoRegisterClassObject API I mentioned above.

If the app is started through COM, it can choose to shutdown itself on the last COM reference release. (This is usually detected through an additional global ref counter that is increased on any object AddRef and decreased on any object Release). However, the app should not shutdown itself, if it detected that the user interacted with its UI. in such case, the shutdown is deferred until the user explicitly closes the last UI (To make that detection easier, the app usually does not show its UI until the user attempts to start it explicitly)

If the app was started by the user and the las UI is closed, the app should check if there are outstanding COM references to any object in it. If there are none, it can shutdown itself. If however, there are COM references, the app should hide the UI, but continue running until the last reference is released.

If the app has reached a point at which it will shutdown, it should revoke all class factory registrations.

Franci Penov
Yes, starting from scratch is probably easier, but the whole point is I have an existing application that is what will be the source of the data and I want to shoe-horn the RTD code into it...I'll have a look at the links. Thanks
Tim
thanks for the additional information. That might be enough to get me going.
Tim
OK, thanks again. My head hurts with all the stuff the wizards create. Now I am starting to remember why I never missed leaving COM behind...
Tim
I'll try the atl wizard. I'm just not sure how to implement/provide/extendthe RTD interface with my own. Not sure how that works.
Tim
A: 

You marshal your code in an ATL Server project. See samples at ATL Server Samples .

lsalamon
ATL Server is used for creating ISAPI extensions with ATL. It will require IIS hosting. It'll work, but it'll be harder to deploy and configure the solution.
Franci Penov