Saturday, June 18, 2005

DCOM revisited

You might remember this post[^]. At the conclusion of that post I thought I had DCOM under control. Poor sad optimist that I was.

Unfortunately, the COM object I was trying to instantiate exposes events to the outside world. When creating such an object from a VB6 app you create the object thusly;

Public WithEvents myObj as MyObjectClass.InSomeActiveXObject

This works easily if the object is located on the local machine. But my object resides on another machine. The VB code doesn't change; that's the magic of DCOM. One runs dcomcnfg and redirects a reference to MyObjectClass.InSomeActiveXObject to the machine on which the object is installed. If all works well the system takes care of setting up the RPC calls to the remote object and it just works.

If it doesn't work then one gets a bunch of cryptic error messages. Which is what happened. I could start the VB app on machine 1, switch to machine 2 and see my object appear in the task list and then see it disappear again a few seconds later. Running the object under the debugger on machine 2 showed that the constructor was being called but that was pretty much it.

If I removed the WithEvents keyword the object was instantiated and remained so; but of course the events weren't raised.

A lot of searches through google and MSDN eventually led me to realise that when an object raises events you have a two way connection. Machine A causes the object to be created on Machine B and the object tries to establish a connection back to Machine A. Obvious in retrospect. So I followed the recommendations on troubleshooting problems in that scenario. Which didn't work. It's a permissions problem but the guidelines didn't solve the problem.

Now it should be obvious that I'm not a DCOM expert. I do have some experience with networking. I also know how to read. And after a week I was no closer to getting it working than I was at the start of the week.

Time for a rethink. We have to get this working at a site half a world away and, just as importantly, we have to keep it working. Yep, we could hire a DCOM consultant who could get it working, now. What if something goes wrong or the network changes? Do we hire the DCOM consultant again? Or maybe another week of painful experimentation would get it working? But if following the Microsoft guidelines doesn't solve the problem it seemed to me that we had a more fundamental problem of maintainability.

So I decided that it was time to re-engineer part of the solution. It's really easy to set up and maintain a one way DCOM transaction. Anyone can do it - even VB programmers. The killer for us was the event mechanism coming back to the originating machine. So I rewrote the object on Machine B to use a mailslot to communicate status back, and wrote a new ActiveX object for Machine A that listens to the mailslot and raises the same events as the original design.

Problem solved and it's a lot easier to maintain. I wrote this[^] article some time ago on CodeProject about mailslots so I already had an easy to use library.

I had to add 3 lines of code and change 4 lines of code in the VB app. Not bad in a 100,000 line app.

No comments: