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

Clarify direction of COM Interop #55

Closed
JoelLeach opened this Issue Oct 11, 2016 · 17 comments

Comments

Projects
None yet
9 participants
@JoelLeach

JoelLeach commented Oct 11, 2016

What is the current thinking on including full support for COM Interop in .NET Standard and .NET Core? It sounds like you would rather not have Windows-specific things like this in Standard. If I'm reading this correctly, apisof.net (currently down) indicates System.Type.GetTypeFromProgID() will be included in the next release: https://webcache.googleusercontent.com/search?q=cache:tYoULw9HjAcJ:https://apisof.net/catalog/System.Type.GetTypeFromProgID(String,String)+&cd=1&hl=en&ct=clnk&gl=us. Can you clarify, or is this still up in the air?

Personally, I will need to work with other technologies via COM Interop for years to come. I hope that doesn't preclude me from moving to .NET Core one day.

@danmosemsft

This comment has been minimized.

Show comment
Hide comment
@danmosemsft

danmosemsft Oct 11, 2016

Member

.NET Standard is a cross platform standard so we've tried to avoid types that are fundamentally platform specific like COM. COM interop and native interop have been segregated into a possible future extension: https://github.com/dotnet/standard/blob/master/extensions/interop/interop.cs.

@weshaggard there are cases where we've removed something because it's interop even though we could leave it (and have it throw) as it doesn't rely on any other problematic types (example Marshal.CleanupUnusedObjectsInCurrentContext) but in other cases we've left them present and expect them to throw (example: Type.GetTypeFromProgID). Should we remove that also?

Note -- in .NET Core's implementation it will currentlythrow NotImplementedException (https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/mscorlib/src/System/RtType.cs#L5333). as opposed to PlatformNotSupportedException. That doesn't seem too big a deal, although we could try to make a pass later.

Member

danmosemsft commented Oct 11, 2016

.NET Standard is a cross platform standard so we've tried to avoid types that are fundamentally platform specific like COM. COM interop and native interop have been segregated into a possible future extension: https://github.com/dotnet/standard/blob/master/extensions/interop/interop.cs.

@weshaggard there are cases where we've removed something because it's interop even though we could leave it (and have it throw) as it doesn't rely on any other problematic types (example Marshal.CleanupUnusedObjectsInCurrentContext) but in other cases we've left them present and expect them to throw (example: Type.GetTypeFromProgID). Should we remove that also?

Note -- in .NET Core's implementation it will currentlythrow NotImplementedException (https://github.com/dotnet/coreclr/blob/32f0f9721afb584b4a14d69135bea7ddc129f755/src/mscorlib/src/System/RtType.cs#L5333). as opposed to PlatformNotSupportedException. That doesn't seem too big a deal, although we could try to make a pass later.

@JoelLeach

This comment has been minimized.

Show comment
Hide comment
@JoelLeach

JoelLeach Oct 11, 2016

Thanks for the clarification.

JoelLeach commented Oct 11, 2016

Thanks for the clarification.

@weshaggard

This comment has been minimized.

Show comment
Hide comment
Member

weshaggard commented Oct 11, 2016

@jkotas

This comment has been minimized.

Show comment
Hide comment
@jkotas

jkotas Oct 11, 2016

Member

including full support for COM Interop in .NET Standard and .NET Core?

There is often incorrect assumption made that "included in .NET Standard" == "works in .NET Core". There are going to be some APIs that will throw PlaformNotSupportedException on .NET Core, also this set be different between Windows and Unix.

Immo goes into details about this in
https://blogs.msdn.microsoft.com/dotnet/2016/10/11/the-week-in-net-on-net-on-net-standard-2-0-nancy-satellite-reign/

COM interop have been segregated into a possible future extension

The parts of COM interop that were possible to segregate have been segregated. You will find quite a bit of COM interop stuff in netstandard.

other cases we've left them present and expect them to throw (example: Type.GetTypeFromProgID). Should we remove that also?

I do not think Type.GetTypeFromProgID should be removed. I believe it gets used quite a bit in real world code.

Member

jkotas commented Oct 11, 2016

including full support for COM Interop in .NET Standard and .NET Core?

There is often incorrect assumption made that "included in .NET Standard" == "works in .NET Core". There are going to be some APIs that will throw PlaformNotSupportedException on .NET Core, also this set be different between Windows and Unix.

Immo goes into details about this in
https://blogs.msdn.microsoft.com/dotnet/2016/10/11/the-week-in-net-on-net-on-net-standard-2-0-nancy-satellite-reign/

COM interop have been segregated into a possible future extension

The parts of COM interop that were possible to segregate have been segregated. You will find quite a bit of COM interop stuff in netstandard.

other cases we've left them present and expect them to throw (example: Type.GetTypeFromProgID). Should we remove that also?

I do not think Type.GetTypeFromProgID should be removed. I believe it gets used quite a bit in real world code.

@JoelLeach

This comment has been minimized.

Show comment
Hide comment
@JoelLeach

JoelLeach Oct 11, 2016

There is often incorrect assumption made that "included in .NET Standard" == "works in .NET Core". There are going to be some APIs that will throw PlaformNotSupportedException on .NET Core, also this set be different between Windows and Unix.

That's going to take some getting used to. The availability of APIs on unsupported platforms may lead a developer to believe an API is fully functional when it is not. Immo did mention future tooling that would notify the developer up front if an API is not supported on a given platform/runtime. That should solve the issue.

JoelLeach commented Oct 11, 2016

There is often incorrect assumption made that "included in .NET Standard" == "works in .NET Core". There are going to be some APIs that will throw PlaformNotSupportedException on .NET Core, also this set be different between Windows and Unix.

That's going to take some getting used to. The availability of APIs on unsupported platforms may lead a developer to believe an API is fully functional when it is not. Immo did mention future tooling that would notify the developer up front if an API is not supported on a given platform/runtime. That should solve the issue.

@gulbanana

This comment has been minimized.

Show comment
Hide comment
@gulbanana

gulbanana Oct 15, 2016

it would be great if there was a way to mark netstandard projects as "expected to be used by tfms". so if you e.g. indicated that something would be used by netcoreapp1.1, the IDE could provide notifications when you used APIs unsupported by that platform - perhaps similar to how multi-TFM intellisense works?

gulbanana commented Oct 15, 2016

it would be great if there was a way to mark netstandard projects as "expected to be used by tfms". so if you e.g. indicated that something would be used by netcoreapp1.1, the IDE could provide notifications when you used APIs unsupported by that platform - perhaps similar to how multi-TFM intellisense works?

@weshaggard

This comment has been minimized.

Show comment
Hide comment
@weshaggard

weshaggard Dec 2, 2016

Member

@gulbanana that is something we are thinking about and would like to try to do as well but it isn't going to be in our up coming releases.

Member

weshaggard commented Dec 2, 2016

@gulbanana that is something we are thinking about and would like to try to do as well but it isn't going to be in our up coming releases.

@weshaggard weshaggard closed this Dec 2, 2016

@jnm2

This comment has been minimized.

Show comment
Hide comment
@jnm2

jnm2 Dec 2, 2016

My fear is that without some type of static type safety in the API preventing you from doing nonportable things without knowing it, this could become a minefield. I know you did this to make it easier to port to, but I can't help feeling it's a compromise that trades off all kinds of reliability.

What would such tooling look like?

jnm2 commented Dec 2, 2016

My fear is that without some type of static type safety in the API preventing you from doing nonportable things without knowing it, this could become a minefield. I know you did this to make it easier to port to, but I can't help feeling it's a compromise that trades off all kinds of reliability.

What would such tooling look like?

@jnm2

This comment has been minimized.

Show comment
Hide comment
@jnm2

jnm2 Dec 2, 2016

It's possible I've missed the picture, so maybe you can help me understand. What is the .NET Standard, if not a set of APIs to build on which is guaranteed to be implemented in any runtime?

jnm2 commented Dec 2, 2016

It's possible I've missed the picture, so maybe you can help me understand. What is the .NET Standard, if not a set of APIs to build on which is guaranteed to be implemented in any runtime?

@danmosemsft danmosemsft reopened this Dec 2, 2016

@weshaggard

This comment has been minimized.

Show comment
Hide comment
@weshaggard

weshaggard Dec 2, 2016

Member

@terrajobst do you have a write-up of what our current thoughts are around how to provide some tooling around the APIs not supported on some platforms.

What is the .NET Standard, if not a set of APIs to build on which is guaranteed to be implemented in any runtime?

The goal of .NET Standard is to provide a common set of APIs that you can depend on being present on a platform that supports .NET Standard. We strive to have everything in the standard supported everywhere but it just isn't possible for every API so there will always be some rough edges but those are meant to be the exceptional cases not the norm.

Member

weshaggard commented Dec 2, 2016

@terrajobst do you have a write-up of what our current thoughts are around how to provide some tooling around the APIs not supported on some platforms.

What is the .NET Standard, if not a set of APIs to build on which is guaranteed to be implemented in any runtime?

The goal of .NET Standard is to provide a common set of APIs that you can depend on being present on a platform that supports .NET Standard. We strive to have everything in the standard supported everywhere but it just isn't possible for every API so there will always be some rough edges but those are meant to be the exceptional cases not the norm.

@gulbanana

This comment has been minimized.

Show comment
Hide comment
@gulbanana

gulbanana Dec 4, 2016

I guess the difference between "depend on being present" and "guaranteed to be implemented" is that in the former case your guarantee is that you can compile against this capability and it will be attempted, but not necessarily succeed, at runtime..?

gulbanana commented Dec 4, 2016

I guess the difference between "depend on being present" and "guaranteed to be implemented" is that in the former case your guarantee is that you can compile against this capability and it will be attempted, but not necessarily succeed, at runtime..?

@yizhang82

This comment has been minimized.

Show comment
Hide comment
@yizhang82

yizhang82 Dec 5, 2016

Member

I guess the difference between "depend on being present" and "guaranteed to be implemented" is that in the former case your guarantee is that you can compile against this capability and it will be attempted, but not necessarily succeed, at runtime..?

@gulbanana Correct. COM interop is actually a good example of this - you'll compile your x-plat app successfully even if you only use COM interop on windows (but the code is there under a if). As long as you correctly detect the current OS and don't use COM interop on non-Windows platform, your app would work in all platforms. If you actually do use it in Linux, for example, your app would blow up.

Member

yizhang82 commented Dec 5, 2016

I guess the difference between "depend on being present" and "guaranteed to be implemented" is that in the former case your guarantee is that you can compile against this capability and it will be attempted, but not necessarily succeed, at runtime..?

@gulbanana Correct. COM interop is actually a good example of this - you'll compile your x-plat app successfully even if you only use COM interop on windows (but the code is there under a if). As long as you correctly detect the current OS and don't use COM interop on non-Windows platform, your app would work in all platforms. If you actually do use it in Linux, for example, your app would blow up.

@jnm2

This comment has been minimized.

Show comment
Hide comment
@jnm2

jnm2 Dec 5, 2016

I would be much more comfortable with this if there was a warning for code that accesses such APIs if the control flow does not clearly indicate that you know you're on the correct platform.

If I'm, say, a NuGet library author starting out with a new project on netstandard2.0, I may do all my testing on Windows since that's what I have. I may not realize when I've taken a dependency on a Windows-only API. It may even be in an infrequently used codepath. Then when someone runs my library on a Mac or Xbox or Android, with the .NET Standard promise of a unified BCL for every platform, they may not find out about the potential time bomb in the library until it's already in production for a while. From there, they will have to come to me and wait until I have spare time for triage and find the issue in my library and publish a new version, and hope that I've spotted them all and have put the OS check at the correct place.

This is what I've been envisioning ever since I heard about this. It does not appeal to me.

A foolproof analyzer would be a great mitigation.

jnm2 commented Dec 5, 2016

I would be much more comfortable with this if there was a warning for code that accesses such APIs if the control flow does not clearly indicate that you know you're on the correct platform.

If I'm, say, a NuGet library author starting out with a new project on netstandard2.0, I may do all my testing on Windows since that's what I have. I may not realize when I've taken a dependency on a Windows-only API. It may even be in an infrequently used codepath. Then when someone runs my library on a Mac or Xbox or Android, with the .NET Standard promise of a unified BCL for every platform, they may not find out about the potential time bomb in the library until it's already in production for a while. From there, they will have to come to me and wait until I have spare time for triage and find the issue in my library and publish a new version, and hope that I've spotted them all and have put the OS check at the correct place.

This is what I've been envisioning ever since I heard about this. It does not appeal to me.

A foolproof analyzer would be a great mitigation.

@JoelLeach

This comment has been minimized.

Show comment
Hide comment
@JoelLeach

JoelLeach Dec 5, 2016

COM interop is actually a good example of this - you'll compile your x-plat app successfully even if you only use COM interop on windows (but the code is there under a if). As long as you correctly detect the current OS and don't use COM interop on non-Windows platform, your app would work in all platforms. If you actually do use it in Linux, for example, your app would blow up.

@yizhang82 That's a good explanation, and I agree with the overall approach. "Guaranteed to be implemented" everywhere only leads back to the Portable Class Libraries approach and an ever-shrinking API set as .NET Core shows up in more places. That said, I do think that many developers will expect .NET Core on Windows to be the "reference implementation" of .NET Standard. It will be confusing to have APIs in the standard that are not functional on the base platform. You have a tough balancing act, to be sure.

In regards to COM interop, I wrote more on the subject here.

I would be much more comfortable with this if there was a warning for code that accesses such APIs if the control flow does not clearly indicate that you know you're on the correct platform.

@jnm2 One of the videos linked above mentions that tooling is coming to help, but I don't know what the timing will be. In practical terms, that should solve the problem without reducing the API surface.

JoelLeach commented Dec 5, 2016

COM interop is actually a good example of this - you'll compile your x-plat app successfully even if you only use COM interop on windows (but the code is there under a if). As long as you correctly detect the current OS and don't use COM interop on non-Windows platform, your app would work in all platforms. If you actually do use it in Linux, for example, your app would blow up.

@yizhang82 That's a good explanation, and I agree with the overall approach. "Guaranteed to be implemented" everywhere only leads back to the Portable Class Libraries approach and an ever-shrinking API set as .NET Core shows up in more places. That said, I do think that many developers will expect .NET Core on Windows to be the "reference implementation" of .NET Standard. It will be confusing to have APIs in the standard that are not functional on the base platform. You have a tough balancing act, to be sure.

In regards to COM interop, I wrote more on the subject here.

I would be much more comfortable with this if there was a warning for code that accesses such APIs if the control flow does not clearly indicate that you know you're on the correct platform.

@jnm2 One of the videos linked above mentions that tooling is coming to help, but I don't know what the timing will be. In practical terms, that should solve the problem without reducing the API surface.

@RickStrahl

This comment has been minimized.

Show comment
Hide comment
@RickStrahl

RickStrahl Dec 21, 2016

It seems to me COM has no place in .NET Standard since it's platform specific technology. It shouldn't be there!

Support for COM should be a framework library that sits on top of standard and hopefully mimics the same interfaces as System.Runtime.Interop provides today. It would just be an OS specific framework assembly.

Anything else would be terribly confusing IMHO.

I realize the main reason this might be included is for compatibility with existing libraries that might expect COM interop features (and there may be quite of that inside of the core of .NET as well as PInvoke), but hopefully this enough of a special case that it can be worked around, especially if the appropriate .NET Core System.Runtime.Interop assemblies match the old signatures.

RickStrahl commented Dec 21, 2016

It seems to me COM has no place in .NET Standard since it's platform specific technology. It shouldn't be there!

Support for COM should be a framework library that sits on top of standard and hopefully mimics the same interfaces as System.Runtime.Interop provides today. It would just be an OS specific framework assembly.

Anything else would be terribly confusing IMHO.

I realize the main reason this might be included is for compatibility with existing libraries that might expect COM interop features (and there may be quite of that inside of the core of .NET as well as PInvoke), but hopefully this enough of a special case that it can be worked around, especially if the appropriate .NET Core System.Runtime.Interop assemblies match the old signatures.

@terrajobst

This comment has been minimized.

Show comment
Hide comment
@terrajobst

terrajobst Dec 21, 2016

Member

It seems to me COM has no place in .NET Standard since it's platform specific technology. It shouldn't be there!

As Jan said above:

The parts of COM interop that were possible to segregate have been segregated. You will find quite a bit of COM interop stuff in netstandard.

Let me provide a bit more context. Not exposing APIs in .NET Standard is easy -- we could always simply subset the types if necessary. However, we think that's problematic. As I explained in my blog post, our goal is to make it possible to target .NET Standard and install packages that allow you to take dependencies on APIs that don't work everywhere (for example, the registry). This allows being compatible with the past and allowing building libraries that are partially portable.

However, we can't add split types across assemblies and thus packages. In other words, by adding a package reference, you'll never see new APIs on exiting types. Yes, sometimes extension methods would support this, but for one they don't work for all kinds of members and secondly it still doesn't allow for compat shims that allows referencing existing .NET Framework that use those APIs.

Thus, for .NET Standard our goal is to maximize API coverage while avoiding adding platform specific concepts. Unfortunately, not all cases are as clean as the Windows registry and COM is a great example.

We believe it's better to accept that some small number APIs will throw on certain platform than making it impossible to support a source/binary compatible API for the platforms that do support the technologies.

Member

terrajobst commented Dec 21, 2016

It seems to me COM has no place in .NET Standard since it's platform specific technology. It shouldn't be there!

As Jan said above:

The parts of COM interop that were possible to segregate have been segregated. You will find quite a bit of COM interop stuff in netstandard.

Let me provide a bit more context. Not exposing APIs in .NET Standard is easy -- we could always simply subset the types if necessary. However, we think that's problematic. As I explained in my blog post, our goal is to make it possible to target .NET Standard and install packages that allow you to take dependencies on APIs that don't work everywhere (for example, the registry). This allows being compatible with the past and allowing building libraries that are partially portable.

However, we can't add split types across assemblies and thus packages. In other words, by adding a package reference, you'll never see new APIs on exiting types. Yes, sometimes extension methods would support this, but for one they don't work for all kinds of members and secondly it still doesn't allow for compat shims that allows referencing existing .NET Framework that use those APIs.

Thus, for .NET Standard our goal is to maximize API coverage while avoiding adding platform specific concepts. Unfortunately, not all cases are as clean as the Windows registry and COM is a great example.

We believe it's better to accept that some small number APIs will throw on certain platform than making it impossible to support a source/binary compatible API for the platforms that do support the technologies.

@terrajobst

This comment has been minimized.

Show comment
Hide comment
@terrajobst

terrajobst Dec 21, 2016

Member

@JoelLeach, let me know if you want more clarification but I believe this thread provides a complete answer :-)

Member

terrajobst commented Dec 21, 2016

@JoelLeach, let me know if you want more clarification but I believe this thread provides a complete answer :-)

@terrajobst terrajobst closed this Dec 21, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment