COM
TL;DR
- Writing a COM client is pretty easy, especially in .NET.
- Writing a COM server is hard. Don’t write a COM server.
- (Unless it’s in .NET, or ATL.)
- COM development is best done in a VM.
COM is not dead, it’s undead. It’s baked into Windows. It will be with us always.
Features?
COM is many things.
- COM is way too big to fit in your head.
- COM delivers the benefits of interfaces and portable binary files.
- But, COM also introduces its own set of problems, lots of details, and tuning parameters.
- Beware of MINFU, which often makes the documentation difficult to digest.
Classic COM Is Hard
The server side can be, anyway. A COM server has more moving parts than a helicopter. Hand rolling a COM ActiveX control using traditional C++/Win32 is often more complex than the business problem it was intended to solve.
- It requires low-level understanding of COM’s inner workings, as well as broad knowledge of the interfaces. In order to troubleshoot any of it, you have to understand pretty much all of it.
- DLL hell. This problem is not unique to COM, but COM tends to accentuate it, particularly through aggregation.
- Good luck debugging.
- Just like the early internet protocols, COM was designed to be used in a trusted environment. Security and licensing are not part of the core design.
- DCOM will not play nicely with your firewall or security team.
When originally released and throughout the ’90s, the idea was that ISVs would publish libraries of COM components, and the task of software development would evolve into mainly connecting them all together, like Legos. This didn’t pan out. Software is just plain complicated, and adding COM to your project does not make it any simpler.
It turns out that in order to use COM components, you have to completely trust their publisher, they have to be very well tested, and they must not break any other controls installed on the target system. The end user generally does not understand what he’s installing, and of course, the software vendor has no way of knowing what’s on the target system.
That being said…
There are use cases where COM is the right fit.
- Creating a COM client is pretty straightforward.
- Windows has a number of COM Support Features and removing them would break everything.
- Communications with InProc servers is fast.
- ATL helps the situation a lot.
- DotNet helps a lot more. If performance is not a concern and you’re not interested in the internals, a .NET COM server is pretty easy to create.
- Components written by Microsoft can be trusted.
- Modern COM supports Assemblies to save you from DLL hell.
- Learning COM is a big part of understanding Windows.
WinRT provides a large collection of system-provided COM objects. It’s a clean, well thought out API. Again, COM is easy from the client side. There are WinRT libraries for many popular languages, including C++, C#, and Rust.
COM will continue to haunt us for the foreseeable future - and possibly eternity.
The Basics
To implement a COM class, you need to
- Write the the class, implementing IUnknown correctly.
- Write a class object which implements IClassFactory, so it can be instantiated.
- Add IDispatch (or a dual interface) if the object is to be available to a scripting environment.
- Add a reference counting mechanism to the server.
- Add self-registration to the server:
- Add the correct entry points if the server is a DLL: DllGetClassObject, DllCanUnloadNow, DllRegisterServer, and DllUnregisterServer.
- Add calls to CoRegisterClassObject if the server is an EXE.
Because this is a lot of boilerplate and is also error prone, you’ll want to use ATL. Let the AppWizard do the heavy lifting for you.
.NET is also your friend.
Subtopics
- IUnknown
- InProc Server (IClassFactory)
- OutProc Server
- Type Information
- Parameter Marshaling
- Error Handling
- OLE Automation
- IStream, ISequentialStream
- IEnumXXX
- Clipboard
- Drag ’n Drop
- Structured Storage and [[Persistence]
- Other Interfaces
- IMoniker and the Running Object Table (ROT)
- COM Events (not to be confused with event objects, or various UI framework events)
- COM Apartment Models
- Component Categories
Types
A large number of related types are part of OLE automation , here are a few of the more common ones.
Most COM objects implement multiple interfaces statically, through multiple inheritance. COM also supports dynamic composition.
Interfaces and user-defined types can be defined in Type Information.
COM+
There are (or were) several types of COM+ objects supported by the AppWizard.
WSH Runtime Library
Windows Scripting Host (WSH) is an administrative API accessible from scripting languages like VB6, JScript and PowerShell.
WinRT
As mentioned before, for new project development, WinRT is your friend.