Tuesday, August 28, 2007

COM is Hard

I get a lot of COM questions. I mean a LOT of COM questions. I eventually answer most of them, but some are easy and some are more difficult. That's one reason I started this blog, to centralize as much knowledge as possible. Once I put post about it I don't have to remember it, it's somewhere on my blog. I haven't had time to post half the things I want to. Eventually I'll get to it all.

COM usually overwhelms people. When someone asks me a questions and I say "oh, that's easy" they respond with "well you know COM". So it got me thinking, why is COM hard? Or I guess a better question is why do people think COM is hard? COM is just a bunch of simple concepts all piled on top of one another. I think most people add ActiveX, MTS, COM+ and whatever other new technology Microsoft added to "COM" by defining some new interfaces and a registration system.

COM is nothing more than a registration system, reference counting memory management and interfaces (classes with only pure virtual methods for C++). Really pretty simple. So why is it hard? My conclutions is the main reason COM is hard is because the registration system sucks! I mean it sucks!

The COM registration system sucks for two reasons. The first and primary reason is GUIDs are nasty to look at and the registry is littered with them making it impossible to clean or know what you are looking at. The second is the initialzation for the COM subsystem, CoInitialize, CoInitializeEx, OleInitialize, CoUninitialize and OleUnInitialize, are horribly complex even though they are very simple functions. These two problems make COM hard. Not just hard, but a monumental task for people who haven't made that epiphany to understanding and spent a lot of time to understand. These are the people who have to code for a living or hobby.

I thought Side-By-Side would solve the first half to the registry problem. Turns out it made the problem even worse because Side-By-Side is even more complex and hardly works. I plea Microsoft to make Side-By-Side easy. All I need is a .ini file that defines all the GUIDs and the .dll or .ocx containing the type library or Assembly. Just one .ini file per applications please. I don't want each .dll or .ocx to have their own .ini file. Just one .ini file for the entire application.

12 comments:

Dmitry Streblechenko said...

Why not use registry-free COM? You really get an ini file (a manifest)...
See here and here

Chris B. said...

Dimitry,

This is the Side-By-Side stuff I was talking about. These examples are very very simple compared to the Delph IDE. Side-By-Side works in a simple case, but once it gets more complicated and the DLLs need to have .manifest files things get so horrible complex it isn't even funny. In fact there was a tool that shipped briefly with Delphi 2007 and wasn't supposed to so it was removed. This tool would generate the .manifest files.

Craig said...

That's part of the problem, but not the only problem. People find the threading abstractions hard to sort out.

Then there's also out-of-process COM and DCOM/COM+, which you don't need to use, but seem to be covered alongside COM even in "basic" documentation, which just adds to the newbie scare factor.

Dmitry Streblechenko said...

Chris,
I probably did not get to play with this enough, but in my experience using a single manifest for the master exe file was very simple, especially if you are trying to use COM dlls from a Win 32 exe and
1. Want to make sure no other app can overwrite your COM libraries.
2. You do not want to mess with the registry installation under limited user rights (which is doable, but you need to modify VCL to make it work - I logged QC 50386 for this issue and posted some sample code to work around teh security issues).

What were the problems that you expecienced?

Anonymous said...

Chris, if you categorized your blog posts you could add the COM category as a resource link in the Delphi WIKI:
http://delphi.wikia.com/wiki/Component_Object_Model

Shawn Oster said...

Good post, as someone that's had to explain COM more than a few times I think you phrased it perfectly: simple concepts layered on top of each other. For a lot of people it's their first introduction to threading models, interfaces, working with the registry and marshalling, all in one go. Of course isn't that programming in a nutshell, simple layered concepts.

@Dmitry, side-by-side isn't exactly easy. It's full of tiny, silly little rules and gotchas about how to name things inside your manifest and where things get put. It's one of those things that if you get right the first time seem very easy but if you don't you can spend hours pulling your hair out. What's more fun is when you get it working perfectly for one OS then it fails on another :)

So exactly *why* was a manifest creation tool pulled from Delphi? Everytime I have to hand build one I think how tedious it all is and that it should be as simple as stringing together dependancies in a tool and having it build the needed manifests and even injecting them into the EXE.

Chris B. said...

Craig,

Correct, all COM based technologies are documented together which causes much of the confusion.

Chris B. said...

Dimitry,

Simple apps work fine using Side-By-Side. It's when those objects use other COM objects is when there becomes a problem. Also throwing .NET into the mix has its own headaches. Versioning and adding the .manifest files as resources. Interesting fact, Delphi .NET handles adding resources much better than C#.

My point is this approach had promis, and I had high hopes, but Microsoft blew it and made it too complicated. When I was looking at it they didn't even have examples up. The examples started showing up after my calls into Microsoft. You should only need to define one .manifest per application but instead are required to define one per module that uses COM.

Thanks for the QC bug. I'll take a look at it here and see what I can do. There aren't attachments like the description says?

Chris B. said...

Anonymous,

I adding labels to CodeGear related posts. You can find COM related posts at this link:

http://chrisbensen.blogspot.com/search/label/COM

I've said it before but I'll say it again. I grant usage to http://delphi.wikia.com of my posts. I want to help support the Delphi and C++Builder community. If another Delphi or C++Builder site wants rights to use my content just ask.

Chris B. said...

Shawn,

For a beginner trying to figure out where to start is often times the most difficult. And obviosly it isn't getting any easier because new technologies are added that sit on top of old technologies. I don't envy the college graduates that have to go back and learn everything until this point.

The manifest creation tool wasn't ever supposed to be delivered. It isn't ready. I figured if someone wanted to try and use it and I told them where to get it they could give it a try. And of course I'd welcome any feedback.

Dmitry Streblechenko said...

Chris,
throwing .Net into anything would cause problems :-)
For the native Win 32 apps you only need one manifest per exe - just the way registry-free COM is implemented: CoCreateInstance() can check what the parent process is and find the corresponding manifest, but it does not know which dll the call is coming from, so only the exe manifest would matter.
Yep, there areno attachments in the QC report, but the changes are relatively minor, 3 or 4 methods in 3 files.

Chris B. said...

Dmitry,

It has been over a year since I looked at it so you must be right about the one .manifest for Win32. Problem is we need the .NET part to work :)

Post a Comment