Since the advent of .NET, COM has been getting nothing but bad press, primarily regarding its lack of full-fidelity type information, and poor cross-language interoperability.

I agree that COM was broken because it lacked full-fidelity type information -- but its type-info woes would have been easy to solve.  In fact,  I often wonder why MS (or maybe even some 3rd party) never replaced IDL with an XML grammar to describe interfaces, their methods, and parameters...  and replaced oleaut32.dll with a new universal marshalling engine based on that XML grammar.  Heck, I almost did that myself, one rainy weekend...

(For the record, I think the problem was VB's inability to interoperate w/ COM's datatypes, not the other way around.)

MS didn't spend billions on .NET just to fix type-info, or to run Java out of business.  .NET is here today because the opportunity existed to knock off many other COM/C++ problems with the same stone:  a managed execution environment to avoid buffer overruns, a gc'd heap to avoid leaks, a loader to support sxs versioning, a virtualized instruction set to run code natively on Pentium/Itanium/Hammer/Transmeta/Whatever, a sandbox in which to run untrusted code, ...  and last but not least, full-fidelity type info to facilitate communication across module, language, and security boundaries.