Non-Cocreatable Class Objects No Longer Wrapped in NDP 2.0 and Later

I dealt with a customer attempting to automate Microsoft Outlook 2003 using the Outlook Primary Interoperability Assembly (Microsoft.Office.Interop.Outlook.dll) for the Microsoft Outlook 11.0 Object Library type library version 9.2.


The type library contains the following items:



coclass MailItem {

    [default] interface _MailItem;

    dispinterface ItemEvents;

    [default, source] dispinterface ItemEvents_10;


interface _MailItem : IDispatch {


dispinterface ItemEvents {


dispinterface ItemEvents_10 {



As you can see, the type library contains the noncreatable coclass MailItem which implements one interface and supports two eventing interfaces (with ItemEvents_10 being the default).


The primary interoperability assembly for the type library contains:


interface   Microsoft.Office.Interop.Outlook._MailItem

interface   Microsoft.Office.Interop.Outlook.ItemEvents_Event

interface   Microsoft.Office.Interop.Outlook.ItemEvents_10_Event

interface   Microsoft.Office.Interop.Outlook.MailItem

      implements Microsoft.Office.Interop.Outlook._MailItem

      implements Microsoft.Office.Interop.Outlook.ItemEvents_10_Event

class       Microsoft.Office.Interop.Outlook.MailItemClass

      implements Microsoft.Office.Interop.Outlook._MailItem

      implements Microsoft.Office.Interop.Outlook.MailItem

      implements Microsoft.Office.Interop.Outlook.ItemEvents_10_Event

      implements Microsoft.Office.Interop.Outlook.ItemEvents_Event


As you can see, the MailItem interface implements just the default interface and the default event interface whereas the MailtItemClass implements every interface. Note that the customer can get to the non-default event interface from a MailItem interface by casting it to an ItemEvents_Event interface.


The customer has code like:


Outlook.Explorer oExp = …


    Outlook.Selection oSel = oExp.Selection;

    if (oSel[1] is Outlook.MailItem)


        //Outlook.MailItem MI =

        //  (Outlook.MailItem) oSel[i]; ß This works

        Outlook.MailItemClass mailItem =

            (Outlook.MailItemClass)oSel[1]; ß This throws exception



When run, the previously listed code throws this exception:


Unhandled Exception: System.InvalidCastException: Unable to cast COM object of type 'System.__ComObject' to class type 'Microsoft.Office.Interop.Outlook.MailItemClass'. COM components that enter the CLR and do not support IProvideClassInfo or that do not have any interop assembly registered will be wrapped in the __ComObject type. Instances of this type cannot be cast to any other class; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface.

at Repro.Main()


The object returned from oExp.Selection is being bound to the type __ComObject instead of the type MailItemClass. Note that it can still be cast to all of the interfaces, but the cast to the class will fail. This code runs without the exception on pre-v2.0 versions of the CLR.


Explanation of Behavior


When a Runtime Callable Wrapper (RCW) is being created for a COM object, the runtime QueryInterfaces the COM object for IProvideClassInfo to determine if the interface is a coclass. If it is a coclass, the CLSID is fetched for the object and the runtime attempts to bind the wrapper object’s type to the typed class wrapper instead of a generic __ComObject.


The system has a hashtable mapping CLSID’s to the appropriate class wrapper types. The normal way that this table is populated is to look in the registry under:



      Assembly ß Strong name of assembly that contains class wrapper

      Class ß Name of the wrapper class


The problem with this is that there are no registry entries for noncreatable coclasses (such as MailItem).


The reason that this used to work pre-v2.0 is because there used to be an optimization in this process that could lead to non-deterministic behavior.


Each Runtime Callable Wrapper (RCW) class that wraps a coclass provides information about the CLSID of the coclass that it wraps. When such a class was loaded in pre-v2.0 versions of the runtime, the CLSID to class mapping was added to the table if it was not already present.


This meant that non-cocreatable COM objects would map to __ComObject prior to loading the correct wrapper class (if the mapping didn’t exist in the registry), but COM objects of the same type would bind to the typed wrapper class after an action had caused the appropriate wrapper class to be loaded once.


Because of the non-determinism of this behavior, this optimization was removed in v2.0.


Solution to the problem


The correct solution is for the customer to not use the coclass wrapper class for noncreatable coclass’s. The customer can cast the interface that they have to any other interface (or event interface) to access to all of the functionality exposed by the coclass wrapper class.


The coclass wrapper class is a flattening of all of the methods of all of the interfaces (including eventing interfaces) implemented by the given COM object. Although simple to use, casting to interfaces gives the programmer access to all of the functionality exposed by the COM object.


I would go so far as to recommend everyone program against the actual interfaces instead of using the flattened typed class object. I think that trying to hide the interface based nature of COM was a bad idea. I feel like other issues caused by this flattening and hiding of interfaces could possibly introduce more breaking changes like this in future releases (note that I said possibly).


This post does bring up the whole topic of the __ComObject. People get very confused and think something is wrong when they see this for the type of a runtime callable wrapper in the debugger. I’ll try to tackle a more general discussion of RCWs and the nature of __ComObject in a future post.

Comments (5)

  1. The term COM object is frequently thrown around, but people really access interfaces off of objects.

  2. If you have seen the error below when using objects from OOM in .NET 2.0 code then the information that

  3. sanjeevkragrawal says:

    HI Mason,

    I am getting below error while working with Outlook 2003 and Outlook Primary Interop Assembly (Microsoft.Office.Interop.Outlook.dll)

    {"Unable to cast COM object of type ‘System.__ComObject’ to interface type ‘Microsoft.Office.Interop.Outlook.MailItem’. This operation failed because the QueryInterface call on the COM component for the interface with IID ‘{00063034-0000-0000-C000-000000000046}’ failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE))."}

    Below is my Code:

    int nCount = objFindItems.Count;

    for (int index = 1; index <= nCount; index++)


            _MailItem objEmail = (_MailItem)(objFindItems[index]);


    PLease help me where I am missing.

    Thanks in advance.


  4. dazed_confused says:

    Hi Mason,

    I’m having trouble reading email from an inbox. The follwing code is an example that intermittantly finds mail items that can’t be cast to _MailItem or MailItem.

    {"Unable to cast COM object of type ‘System.__ComObject’ to interface type ‘Microsoft.Office.Interop.Outlook._MailItem’. This operation failed because the QueryInterface call on the COM component for the interface with IID ‘{00063034-0000-0000-C000-000000000046}’ failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE))."}

    But the object still has a type of IPM.Note and a call to the VB Function Information.TypeName() shows it is a "MailItem"

    I usually happens at the same item in the inbox but if i wait a while it will start happening on a different item instead.

    InvokeMethod only allows me access to one of the three properties i need ("Subject"), while querying the properties "Body" and "SenderName" on an uncast Object will cause a TargetInvocationException. Otherwise i would just resort to using InvokeMethod without casting at all


    // Connect to outlook and open inbox

    ApplicationClass outlook = new ApplicationClass();

    NameSpace mapi = outlook.GetNamespace("MAPI");

    mapi.Logon("", "", true, false);

    MAPIFolder rootFolder = mapi.Folders["Mailbox – idms support"];

    MAPIFolder subFolder = rootFolder.Folders["Inbox"];

    Items items = subFolder.Items;

    items = items.Restrict("[MessageClass] = ‘IPM.Note’");

    int i = 0;

    foreach (Object item in items)




           _MailItem mail = (_MailItem)item;


       catch (InvalidCastException e)


           Type t = item.GetType();

           string messageClass = (string)t.InvokeMember("MessageClass", System.Reflection.BindingFlags.GetProperty, null, item, null);






    return new CheckResult(ResultType.Null, "");

    ## CODE END

  5. mmarquard says:

    We have an Outlook Add-in written in .NET 1.1 that raises exactly the exception mentioned above. The reason is that we use the MailItemClass rather than MailItem. We need to do this is we wish to capture the ItemSend event.

    Even if we try to add the handler explicitly, i.e.

       AddHandler m_olMailItem.ItemSend, AddressOf m_olMailItem_ItemSend

    we get the exception in the routine – despite the fact that we do not cast to a mailitemclass. Any details on how we should leverage events exposed in MailItemClass would be great.

Skip to main content