Skip to content
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

Targeting net5.0-windows still causes 'API X is supported on windows' errors #14502

Closed
mareklinka opened this issue Nov 11, 2020 · 20 comments
Closed
Assignees
Labels
untriaged Request triage from a team member

Comments

@mareklinka
Copy link

mareklinka commented Nov 11, 2020

Hello. I have a project migrated from netcoreapp3.1 to net5.0 that references the System.DirectoryServices 5.0.0 nuget. This nuget targets Windows only (the assembly is marked with [assembly: SupportedOSPlatform("windows")]):
image

So trying to compile that project with TFM net5.0 errors out with CA1416:

error CA1416: 'DirectorySearcher' is supported on 'windows'

According to the documentation for that rule (emphasis mine):

A violation only occurs if the project does not target the supported platform (net5.0-differentPlatform). This also applies to multi-targeted projects. No violation occurs if the project targets the specified platform (net5.0-platformName).

From that I surmised that switching the project file to target net5.0-windows should be enough to compile the project. Unfortunately, this is not the case - I'm still getting the CA1416 violations.

My csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0-windows</TargetFramework>
    <OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>..\..\..\build\</OutputPath>
    <TreatWarningsAsErrors>True</TreatWarningsAsErrors>
    <TreatSpecificWarningsAsErrors />
    <PlatformTarget>x64</PlatformTarget>
    <NoWarn>1701;1702;1591</NoWarn>
  </PropertyGroup>

    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <OutputPath>..\..\..\build\</OutputPath>
    <DebugSymbols>true</DebugSymbols>
    <TreatWarningsAsErrors>True</TreatWarningsAsErrors>
    <TreatSpecificWarningsAsErrors />
    <PlatformTarget>x64</PlatformTarget>
    <NoWarn>1701;1702;1591</NoWarn>
  </PropertyGroup>

  ...

</Project>

dotnet build still caused CA1416 errors. When I add [assembly: SupportedOSPlatform("windows")] to the assembly, it compiles correctly. So either the documentation for rule CA1416 is wrong or something is not working correctly with the net5.0-windows TFM. Or I'm missing something crucial here.

Can you please take a look at this?

EDIT

I should have mentioned that I'm using the current GA versions of dotnet 5.0 SDK:

.NET SDK (reflecting any global.json):
 Version:   5.0.100
 Commit:    5044b93829

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19042
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\5.0.100\

Host (useful for support):
  Version: 5.0.0
  Commit:  cf258a14b7

.NET SDKs installed:
  3.1.301 [C:\Program Files\dotnet\sdk]
  3.1.402 [C:\Program Files\dotnet\sdk]
  5.0.100-preview.8.20417.9 [C:\Program Files\dotnet\sdk]
  5.0.100 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.1.23 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.23 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.0-preview.8.20414.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.23 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.0-preview.8.20407.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.0-preview.8.20411.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
@mareklinka
Copy link
Author

I think I managed to trace the issue down. The problem seems to be caused by the fact that we have a shared project (shproj) in our solution and this shared project contains our AssemblyInfo.cs. The .projitems file contains:

<PropertyGroup>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup>
    <Compile Include="$(MSBuildThisFileDirectory)AssemblyInfo.cs" />
</ItemGroup>

And this seems to be interfering with the net5.0-windows TFM from marking the assembly as Windows-only. I suspect that the compiler would emit an [assembly: SupportedOSPlatform("windows")] annotation in the AssemblyInfo.cs but this doesn't work because AI generation is disabled.

This theory seems to be further supported by the following minimal repro:
sdk-repro.zip

The repro is a trivial console app with TFM set to net5.0-windows and GenerateAssmeblyInfo set to false. Attempting to compile this results in:

> dotnet build --no-incremental
Microsoft (R) Build Engine version 16.8.0+126527ff1 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
C:\Source\Personal\sdk-repro\Program.cs(10,35): warning CA1416: 'DirectorySearcher' is supported on 'windows' [C:\Source\Personal\sdk-repro\sdk-repro.csproj]
  sdk-repro -> C:\Source\Personal\sdk-repro\bin\Debug\net5.0-windows\sdk-repro.dll

Build succeeded.

C:\Source\Personal\sdk-repro\Program.cs(10,35): warning CA1416: 'DirectorySearcher' is supported on 'windows' [C:\Source\Personal\sdk-repro\sdk-repro.csproj]
    1 Warning(s)
    0 Error(s)

This should work regardless whether I generate an assembly info or create it manually. Otherwise users can get into a situation where they are targeting net5.0-windows and the resulting assembly doesn't reflect this.

@yevgeni-zolotko
Copy link

We experience the same issue with our code. We use a shared AssemblyInfo.cs file in our projects, and <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
The false-positive warning we are getting are

warning CA1416: 'Marshal.Release(IntPtr)' is supported on 'windows'
warning CA1416: 'Marshal.GetIUnknownForObject(object)' is supported on 'windows'

on net5.0-windows

@mareklinka
Copy link
Author

@yevgeni-zolotko Until this is properly resolved, you can work around the issue by putting [assembly: SupportedOSPlatform("windows")] into your shared AssemblyInfo.cs. This should get rid of the warning.

@yevgeni-zolotko
Copy link

@mareklinka Thank you, the following worked for me:

#if NET5_0
[assembly: System.Runtime.Versioning.SupportedOSPlatform("windows")]
#endif

@TonyValenti
Copy link

Is there an ETA on an official fix for this? We're having the same issues in our projects.

@kirsan31
Copy link

#if NET5_0
[assembly: System.Runtime.Versioning.SupportedOSPlatform("windows")]
#endif

removes only CA1416: xxx is supported on 'windows' messages. And what to do with dozens of
CA1416 xxx is supported on 'Windows' 7.0 and later from all user controls that target net5.0-windows?

@mareklinka
Copy link
Author

@kirsan31 The parameter in SupportedOSPlatform can contain OS versions as well, just like the .NET 5 TFMs: https://github.com/dotnet/designs/blob/main/accepted/2020/net5/net5.md. Therefore you should be able to do

[assembly: System.Runtime.Versioning.SupportedOSPlatform("windows7.0")]

Disclaimer: I have not tested this behavior so your mileage may vary.

@kirsan31
Copy link

[assembly: System.Runtime.Versioning.SupportedOSPlatform("windows7.0")]

Thank you, I've already tried and this is not helped :(
I was trying:
windows7.0
windows7
windows6.1

Also I am not understand why windows7.0 and not windows6.1? What about windows server 2012R2 (6.3)???

Overall if I build user control with net5.0-windows and it's automatically mark it with 'Windows' 7.0 and later then when I build an app with net5.0-windows (using this control) there must be no warning CA1416 xxx is supported on 'Windows' 7.0 and later.

P.s. I've completely disabled CA1416 for now...

@ekgurney14
Copy link

I was able to get this to go away by moving all my [assembly:] to csroj using . Unfortunately the parameters for those need to be strings (out of the box anyway: dotnet/msbuild#2281 (comment)).
For right now I deleted the [assembly: ComVisible] attributes from my project that VS put there by default. It would be really nice if this issue was fixed.

@dove
Copy link

dove commented Jan 14, 2021

@kirsan31 I've added just the following and only the following
[assembly: System.Runtime.Versioning.SupportedOSPlatform("windows7.0")]

be sure not to add after adding
[assembly: System.Runtime.Versioning.SupportedOSPlatform("windows")]

Adding both only removes only the windows warning but not the Windows 7.0 warning. Adding the first removes both.

@Epic-Santiago
Copy link

Epic-Santiago commented Apr 28, 2021

I have the same issue with the project below. This line of code will give warning CA1416:

Microsoft.Win32.Registry.LocalMachine.GetSubKeyNames();

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net5.0-windows</TargetFramework>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
  </PropertyGroup>
  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Win32.Registry" Version="4.7.0" />
  </ItemGroup>
</Project>

@buyaa-n
Copy link
Member

buyaa-n commented Apr 28, 2021

@Epic-Santiago because you disabled generating AssemblyInfo.cs <GenerateAssemblyInfo>false</GenerateAssemblyInfo> SDK cannot generate the expected assembly level SupportedOSPlatform("windows") attribute.
Please add [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows")] attribute anywhere in your assembly ("windows7.0" in case you are using that version).

@buyaa-n
Copy link
Member

buyaa-n commented Apr 28, 2021

@dsplaisted @sfoslund is it possible to add the SupportedOSPlatform attribute somewhere else when GenerateAssemblyInfo is disabled?

@dsplaisted
Copy link
Member

GenerateAssemblyInfo is a big hammer which turns off all (or almost all) of the automatic assembly attribute generation. So I don't think there's a good way for us to still generate SupportedOSPlatform attributes when it's disabled.

I would suggest one of the following for projects:

  • Don't set GenerateAssemblyInfo to false, rather set the individual properties to false which control automatic attribute generation for attributes which are already defined in user source code. Here's the list of these properties:
    <GenerateAssemblyCompanyAttribute Condition="'$(GenerateAssemblyCompanyAttribute)' == ''">true</GenerateAssemblyCompanyAttribute>
    <GenerateAssemblyConfigurationAttribute Condition="'$(GenerateAssemblyConfigurationAttribute)' == ''">true</GenerateAssemblyConfigurationAttribute>
    <GenerateAssemblyCopyrightAttribute Condition="'$(GenerateAssemblyCopyrightAttribute)' == ''">true</GenerateAssemblyCopyrightAttribute>
    <GenerateAssemblyDescriptionAttribute Condition="'$(GenerateAssemblyDescriptionAttribute)' == ''">true</GenerateAssemblyDescriptionAttribute>
    <GenerateAssemblyFileVersionAttribute Condition="'$(GenerateAssemblyFileVersionAttribute)' == ''">true</GenerateAssemblyFileVersionAttribute>
    <GenerateAssemblyInformationalVersionAttribute Condition="'$(GenerateAssemblyInformationalVersionAttribute)' == ''">true</GenerateAssemblyInformationalVersionAttribute>
    <GenerateAssemblyProductAttribute Condition="'$(GenerateAssemblyProductAttribute)' == ''">true</GenerateAssemblyProductAttribute>
    <GenerateAssemblyTitleAttribute Condition="'$(GenerateAssemblyTitleAttribute)' == ''">true</GenerateAssemblyTitleAttribute>
    <GenerateAssemblyVersionAttribute Condition="'$(GenerateAssemblyVersionAttribute)' == ''">true</GenerateAssemblyVersionAttribute>
    <GenerateRepositoryUrlAttribute Condition="'$(GenerateRepositoryUrlAttribute)' == '' and !('$(TargetFrameworkIdentifier)' == '.NETFramework' and $([MSBuild]::VersionLessThan($(TargetFrameworkVersion), 4.5)))">true</GenerateRepositoryUrlAttribute>
    <GenerateNeutralResourcesLanguageAttribute Condition="'$(GenerateNeutralResourcesLanguageAttribute)' == ''">true</GenerateNeutralResourcesLanguageAttribute>
    <GenerateAssemblyMetadataAttributes Condition="'$(GenerateAssemblyMetadataAttributes)' == ''">true</GenerateAssemblyMetadataAttributes>
    <IncludeSourceRevisionInInformationalVersion Condition="'$(IncludeSourceRevisionInInformationalVersion)' == ''">true</IncludeSourceRevisionInInformationalVersion>
    <GenerateInternalsVisibleToAttributes Condition="'$(GenerateInternalsVisibleToAttributes)' == ''">true</GenerateInternalsVisibleToAttributes>
  • Don't use AssemblyInfo.cs type files at all. Let these attributes be generated automatically, setting their values via MSBuild properties. For example, the Company property determines the value for the automatically generated AssemblyCompanyAttribute. These values can be shared between projects with Directory.Build.props or Directory.Build.targets

@Epic-Santiago
Copy link

Thanks for the feedback. Adding the SupportedOSPlatform("windows") assembly attribute works. But there's a bit more nuance to this issue. Because if I don't include Microsoft.AspNetCore.App, the issue doesn't occur. What AspNetCore has to do with any of this is beyond me.

We can look at migrating to a props or target file. As you correctly guessed above, we use a shared AssemblyInfo so that we have common attributes across thousands of projects. We've been doing this for a long time, well before SDK-style projects required disabling GenerateAssemblyInfo. Moving to props/targets will be some work.

@buyaa-n
Copy link
Member

buyaa-n commented Apr 29, 2021

Because if I don't include Microsoft.AspNetCore.App, the issue doesn't occur. What AspNetCore has to do with any of this is beyond me.

Weird, Microsoft.AspNetCore.App is cross-platform it should not be caused by that.
Previously you mentioned Microsoft.Win32.Registry.LocalMachine.GetSubKeyNames(); is warned, which is expected as Microsoft.Win32.Registry is windows only

@Epic-Santiago
Copy link

Epic-Santiago commented Apr 29, 2021

It's warning about the registry. But if I remove the AspNetCore framework reference, I don't have the issue. See my sample project above. You can trivially repro the issue. Then remove the FrameworkReference and the issue disapears.

@MisinformedDNA
Copy link

If we are targeting net5.0-windows, shouldn't SupportedOSPlatform be implicit?

@dsplaisted
Copy link
Member

If we are targeting net5.0-windows, shouldn't SupportedOSPlatform be implicit?

The mechanism by which it is implicit involves automatically generating the SupportedOSPlatform attribute. With assembly attribute generation disabled, then it's not implicit anymore.

@marcpopMSFT
Copy link
Member

Old bug triage: Per Daniel's comment above, there is a workaround by setting the assembly attribute directly:

#if NET5_0
[assembly: System.Runtime.Versioning.SupportedOSPlatform("windows")]
#endif

or turning back on GenerateAssemblyInfo.

@marcpopMSFT marcpopMSFT closed this as not planned Won't fix, can't repro, duplicate, stale May 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
untriaged Request triage from a team member
Projects
None yet
Development

No branches or pull requests