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.
Ideally this is provided for VS2008, but any version would work.
Thanks.
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.
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:
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.