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
Description
When implementing an IDispatch apartment threaded object on net7.0, an exception is thrown when calling
Marshal.GetIDispatchForObject. Non-.Net callers getE_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, butStandardOleMarshalObjectis exclusively used with COM. I would propose that[ComVisible(true)]be re-added toStandardOleMarshalObject, the requirement for[ComVisible(true)]to be reduced, or the need to re-implementStandardOleMarshalObjectbe documented. In testing, adding the attribute is sufficient to avoid the exception.Reproduction Steps
Create a new
net7.0-windowsconsole program. Add the following to Program.cs: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:
If the type is passed to a COM server or registered with
CoRegisterClassObjectinstead ofGetIDispatchForObject, no exception is thrown in the server andE_NOINTERFACEis 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
StandardOleMarshalComObjectas a base class.Configuration
dotnet 7.0.401
Windows 11 22H2 (22621.2428)
Reproducible with
Platformx86 or x64Presumed to be applicable to .Net 5..8 and all platforms
Other information
Loosely related: #80422