-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide a COM source generator #66674
Comments
Tagging subscribers to this area: @dotnet/interop-contrib Issue DetailsWe plan to provide a COM source generator to enable developers to interoperate with unmanaged COM interfaces without using the built-in COM Interop subsystem as per our Source Generator COM design. This issue tracks the various tasks that implementing this source generator will require. Not all of these tasks will be completed in .NET 7 (in fact this list intentionally includes significantly more work than we will do in .NET 7 to provide a roadmap over a few versions). Checkpoint 1: MCG-replacement
Checkpoint 2: WinForms compatibility WinForms is primarily
Checkpoint 3: Activation support For parity with the built-in system, providing an easy mechanism for activating a COM object is desireable, if lower priority.
Checkpoint 4: IDispatch support If we find enough demand, we should consider providing more extensive
Checkpoint 5: TLB support
|
I'm currently writing a managed library that wraps the COM interfaces that CoreCLR supports for diagnostics (
|
We've considered such a strategy, but we want to get some performance numbers before we decide to go one direction or the other (or a blend of both).
Yes, we plan to support the same features we support with
We're hoping to get checkpoint 1 done in the .NET 7 time frame, but I don't want to make any promises. |
How would this look in practice, by the way? E.g. if I define [GeneratedComInterface(typeof(MyComWrappers))]
[Guid("4b69d271-5c99-4f95-b1eb-381e6e689f1a")]
partial interface IMyComInterface
{
void Foo();
} and I'm not familiar with the exact set of constructs supported by
That's fine, I was just wondering what the plan was, with the understanding that plans can change. |
This is still under discussion. The current prevailing idea is to match the built-in system where we do HRESULT checking by default unless the user provides the
We have some custom marshallers for Additional ideas (like synthesizing a length parameter into the native signature) have not been proposed or implemented yet. If you're interested in that feature, I think it's worthwhile filing a separate issue for the team to discuss it.
👍 |
Is there an ETA for the ComWrappers source generator? |
We are working on a prototype now that might be used for some internal parts of the dotnet/runtime repo. The plan would be to iterate early .NET 8 and hopefully have something in one of the later .NET 8 previews for public consumption. |
I'd appreciate if this was usable for creating an out-of-process COM server. |
I have a question about the Source Generator COM design doc, and the intended scope of the COM wrappers for
This is the scenario I'm concerned with - creating NativeAOT outputs (add-in libraries or standalone programs) that call Office COM APIs. The problem with a lack of Even when using a pre-compiled PIA, there are common code patterns that require the
The one part I can't see yet (and have not tried myself) is how to fill in, by source generation or extra wrapper code, a way to make calls like the above work when changing to NativeAOT. There are some related quirks around the PIA code and how it is called from C# - for example related to indexed properties (which appear in PIA code and can be called from C# for embedded PIA scenarios but can't be authored in normal (or source generated) C# code). Due to the .NET versioning limitations for in-process add-ins, we will be stuck on .NET 6 (together with .NET Framework) for making Office add-ins until we have a viable NativeAOT approach. From the discussion around COM Wrappers, and the source generators here, it looks like we will have a comprehensive approach for exposing COM objects from NativeAOT libraries (perhaps with third-party tools like dscom for type library generation). Hence, I want to campaign for a higher priority also for supporting existing C# code that calls COM libraries, unlocked by some plan for |
@AaronRobinsonMSFT @jkoritzinsky Could you please help me understand the intended scope of the COM / AOT support in .NET 8 and in near future versions relating to the Office applications (particularly Excel). If I intend for an AOT compiled library to talk to Excel via COM, my current understanding is that
If we want to do Office interop with .NET 8 AOT, how do you recommend we approach this? |
@AaronRobinsonMSFT @jkoritzinsky, we're trying to build wrappers around Excel C/COM APIs (example project) it would be very helpful to shed some light on @govert's questions. Thanks in advance! |
Correct.
There is no built-in support, but one could imagine an AOT scenario where all the known
Yes.
Yes.
The interfaces would currently need to be redefined using
Yes, but narrowly. Support for
Redefine the needed interfaces using |
@AaronRobinsonMSFT Thank you very much for the reply and setting our expectations for the current COM / AOT support. For the COM objects we need to expose as CCWs to Excel (e.g. to support Ribbon extensions or real-time data sources) we would need to implement the Could you please clarify the status of the C# 'dynamic' infrastructure under Native AOT? I'm trying to understand whether one might revisit the work from #33060 (which implements the COM / dynamic binder support), but replace the built-in COM features with ComWrappers. It might help to focus on the (hopefully) simpler cases that the Office COM model requires. But this would still need to the C# dynamic binder to work under AOT against the user-code implemented 'RCW's. For reference (please redirect if this is off-topic), here's a snippet where runtime expression trees work, but using System.Linq.Expressions;
Console.WriteLine("Hello, World!");
// This works under NativeAOT
var lambda2 = Expression.Lambda(
Expression.Add(
Expression.Constant(1.3, typeof(double)),
Expression.Constant(2.7, typeof(double))
)
);
Func<double> getResult = (Func<double>)lambda2.Compile();
Console.WriteLine(getResult());
// This crashes under NativeAOT
dynamic d1 = 1.3;
dynamic d2 = 2.7;
double d = (double)(d1 + d2); // <<<<< NRE or access violation here
Console.WriteLine(d); |
|
@jkotas Indeed I do get such warnings, both for the I suppose my question is whether |
You can make it work by providing trimming and AOT hints, but it is very error prone. We do not recommend it. |
To confuse things more, the
Should we expect code to fail with AOT when it is working with this configuration? |
Trim warnings indicate that some code may not work as expected after trimming. The trimmed app can work today and start failing after next .NET SDK update. It can work with JIT and fail with native AOT. This unpredictable behavior is by-design. |
Hi! I'd like to add to this list of work items the need to properly support ActiveX interop bindings - the ones generated by aximp.exe on top of the COM interop bindings generated by tlbimp.exe in current .NET build tooling. We need this in Remote Desktop Manager for the Microsoft RDP ActiveX control on Windows, the only exhaustive interface for third-party integration of the first-party RDP client. Even if we integrate FreeRDP, a project which I have created years ago, it will likely never reach 100% feature parity with the original, so customers really want the option to use official RDP client. For this reason, continued support for the RDP ActiveX control in .NET is business critical to us, as RDP is the most important protocol we support in our product. This being said, we still ship .NET with regular JIT assemblies, so we're not in a rush to try Native AOT. However, the Remote Desktop Manager application startup time is an annoyance we've had since forever, so I would be lying if I didn't at least have my eye on experimenting with Native AOT for Remote Desktop Manager at some point in the future. I'm just looking at what would be blocking it, and lack of RDP ActiveX support would be a non-starter for us for the reasons listed above. Enough of the business aspect of things: when it comes to the RDP ActiveX, I maintain MsRdpEx, a project which extends the original RDP ActiveX with additional features our customers need, but Microsoft doesn't provide. The RDP ActiveX is probably the most widely used ActiveX component in .NET today, and you'll find AxMSTSCLib.dll, MSTSCLib.dll in a lot of Windows .NET applications that use RDP. We ship a code signed nuget package with everything needed to load and use the Microsoft RDP ActiveX component from .NET, which includes the ability for manual COM activation of the ActiveX DLL by path. COM Activation is mentioned earlier - we need manual COM Active by DLL path to load rdclientax.dll from MSRDC, which contains an unregistered RDP ActiveX interface compatible with the one from mstscax.dll. Even then, being able to load COM interfaces without registration is a huge plus, and in this case, it allows us to load both mstscax.dll and rdclientax.dll on a per-session basis inside Remote Desktop Manager, based on connection preferences. As for the build tooling, I took notes on how to regenerate everything from the type library for both C# and C/C++. This should come in handy when comparing the old tooling with the new for experimentation. While aximp.exe has a way to generate source code, tlbimp.exe only generates an assembly straight as MSIL, which unfortunately doesn't decompile to clean C# code with tools like ILSpy. This currently limits the ability to control how the assembly is built, and it has annoying things like a hardcoded reference to net40 as the target framework. It doesn't break the build, but it does cause build warnings, even if the assembly is in fact compatible with modern .NET. As for the ActiveX interop method, one can do dynamic calls through IDispatch, or call the vtable functions directly. In the case of the RDP ActiveX, I am fairly certainly that the calls are always done through vtable with the generated interop bindings. I don't know of an ActiveX component that would not support the vtable calls, and even then, it would still be possible to generate stubs wrapping IDispatch if it's ever needed. However, for our needs, we are more than happy to use the vtable calls without the runtime calling through IDispatch, it's much faster anyway. Last but not least: the ActiveX bindings are meant to be consumed by WinForms. We're WinForms users, and we'd like to keep using WinForms in the future. I don't mind if the new build tooling can generate ActiveX bindings for other .NET UI frameworks, but it would be important to coordinate with the WinForms team to ensure compatibility of the newer bindings. One last thing: when adding ActiveX components in WinForms from Visual Studio, it generates a .resx with a serialized BinaryFormatter OcxState object which is then loaded in the designer-generated source code. Needless to say that this causes deprecation warnings in .NET 8 as this kind of object serialization is scheduled to be entirely removed in .NET 9. I manually deleted those resources and set OcxState to null in the designer-generated source code, it didn't seem to cause problems. However, someone from the Visual Studio team should definitely look into fixing this issue in the WinForms designer. I have no idea what this OcxState object is used for, and how to create it dynamically instead of deserializing it from a resource. I hope this clarifies the need for modernized ActiveX support in .NET! Feel free to reach out for any assistance, I'll be happy to help. |
Its serialized state of the ActiveX control, basically a binary blob for the control to store whatever designer state it wants to preserve to runtime thats not configurable through control properties. More complex ActiveX controls may have custom UI to configure things instead of just using properties. If you don't provide one when instantiating it the control implicitely uses default state, which should work fine as long as you didn't configure anything in the designer of the ActiveX control that affected its internal state. It should be possible for the new designer to just store it as a byte array or something along those lines. |
@awakecoding I took a look at the TLB through the oleview tool (shows the IDL source for a TLB, is part of the Windows SDK installed by VS) and it doesn't look very complicated, should be possible to write the interop manually for me. Is there an open source example for Desktop Framework using that ActiveX control? I'd consider doing a proof of concept port if you want to see how well it works in .NET 8 - I've been working with the WinForms project in the past to improve interop support and having another ActiveX control thats used in practice could help interop quality, we've been struggling to find relevant usecases to test the ActiveX support against last I worked with them. PS: feel free to take the conversation about a PoC to somewhere else on git (if you have a project), or to mail (see my git profile), to not get offtopic on this one |
@weltkante I have a sample .NET application just to test the .NET interop, it's nothing fancy but it's there in the MsRdpEx repository. I have build instructions for MsRdpEx, it's not too difficult to get started, and I'd be happy to assist with experiments on that repository if you want to take the discussion there. I would welcome an experimentation branch from you if you have an idea how to try it! You can also reach me on Twitter/X. |
It is a bit disappointing that properties aren't supported at all by COM source generators. This makes it impossible to use generated interop as a (mostly) source-compatible drop-in replacement. It would definitely be desireable to consider property support for the future, maybe annotate the property methods with an attribute if you need it to define VTable position. I saw something about a |
All part of a V1 release. I think it is worth having the conversation in .NET 9. I don't think we have an issue for property support, @jkoritzinsky? |
I don't think we have one yet. I'll open one today. Edit: Opened at #96502 |
Many developers have a lot of demands for using tlb lib import in AOT , but it is not supported in Net9. I believe this will be popular when it is supported. Is there a plan to support it in .Net10? @jkoritzinsky? @alexrp @awakecoding @lukedays @govert @agocke |
We plan to provide a COM source generator to enable developers to interoperate with unmanaged COM interfaces without using the built-in COM Interop subsystem as per our Source Generator COM design.
This issue tracks the various tasks that implementing this source generator will require. Not all of these tasks will be completed in .NET 7 (in fact this list intentionally includes significantly more work than we will do in .NET 7 to provide a roadmap over a few versions).
Checkpoint 1: MCG-replacement
ComObject
type that implements any required infrastructure to provide implementations of a COM interface.IDynamicInterfaceCastable
-related)ComObject
instance that wraps a nativeIUnknown*
through a user-definedpartial
ComWrappers
-derived type.ComObject
using the above functionality.IUnknown*
that represents a managed non-ComObject
object through a user-definedpartial
ComWrappers
-derived type.IUnknown*
wrapper using the above functionalityCheckpoint 2: WinForms compatibility
WinForms is primarily
IUnknown
-based COM, but there is some usage ofIDispatch
-based COM, primarily in the accessibility space. We would like to help support making WinForms trim-friendly, so we want to provide these features in the generator to support them.BSTR
strings. AddBStrStringMarshaller
to source generator #69213VARIANT
s without typelib related support (no user-defined record types): Implement the ComVariant struct, the ComVariantMarshaller type, and generator integration #93635SAFEARRAY
sIDispatch
, or provide guidance for implementing stubbed-out support.IDispatch
implementation can be stubbed out withE_NOTIMPL
errors: https://docs.microsoft.com/en-us/windows/win32/winauto/dual-interfaces--iaccessible-and-idispatchCheckpoint 3: Activation support
For parity with the built-in system, providing an easy mechanism for activating a COM object is desireable, if lower priority.
EnableComHosting
switch in the SDK for built-in COM.Checkpoint 4: IDispatch support
If we find enough demand, we should consider providing more extensive
IDispatch
support (excluding TLB-related dependencies)IDispatch
-based interfaces with well-definedDispId
valuesIDispatch
-based interfaces with generator-definedDispId
valuesdynamic
compatibility forIDispatch
-based COM object wrappers.Checkpoint 5: TLB support
VARIANT
orIDispatch
-related scenarios.Features to consider
The text was updated successfully, but these errors were encountered: