Skip to content

Apartment threaded IDispatch server throws InvalidOperationException or fails to marshal #94749

@mgaffigan

Description

@mgaffigan

Description

When implementing an IDispatch apartment threaded object on net7.0, an exception is thrown when calling Marshal.GetIDispatchForObject. Non-.Net callers get E_NOINTERFACE. The same code works on .Net Framework.

This seems to be related to removing [ComVisible(true)] from many types - which is understandable in general, but StandardOleMarshalObject is exclusively used with COM. I would propose that [ComVisible(true)] be re-added to StandardOleMarshalObject, the requirement for [ComVisible(true)] to be reduced, or the need to re-implement StandardOleMarshalObject be documented. In testing, adding the attribute is sufficient to avoid the exception.

Reproduction Steps

Create a new net7.0-windows console program. Add the following to Program.cs:

Marshal.GetIDispatchForObject(new Example());

[ComVisible(true)]
public class Example : StandardOleMarshalObject
{
}

Expected behavior

The example program should not throw an exception (the type will be available to IDispatch callers).

Actual behavior

The following exception is thrown:

System.InvalidOperationException: Type 'DispTarget' has a ComVisible(false) parent
'System.Runtime.InteropServices.StandardOleMarshalObject' in its hierarchy, therefore QueryInterface calls for IDispatch or class interfaces are disallowed.
    at System.Runtime.InteropServices.Marshal.GetIDispatchForObjectNative(Object o)
    at Program.<Main>$(String[] args) in C:\dev\source\repos\ComDispatchDemo\DemoDispatchServer\Program.cs:line 8

If the type is passed to a COM server or registered with CoRegisterClassObject instead of GetIDispatchForObject, no exception is thrown in the server and E_NOINTERFACE is returned the caller.

Regression?

Yes. The same code on net48 runs without issue.

Known Workarounds

Copy/paste the implementation of StandardOleMarshalComObject.cs into the project, and add the [ComVisible(true)] attribute.

Alternately, if the object does not require apartment threading, remove StandardOleMarshalComObject as a base class.

Configuration

dotnet 7.0.401
Windows 11 22H2 (22621.2428)
Reproducible with Platform x86 or x64
Presumed to be applicable to .Net 5..8 and all platforms

Other information

Loosely related: #80422

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    No status

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions