Skip to content

Conversation

@haileymck
Copy link
Member

@haileymck haileymck commented Dec 10, 2025

first commit:

  • removes the target framework option
  • calls dotnet msbuild to get targetframework(s)
  • returns the lowest target framework (here net 10 is higher than net 8)

second commit:

  • makes it so that the "prerelease" option only shows if net 10 is the target framework

third coimmit:

  • logs instead of throw when unsupported framework is in the project

when project has target framework not supported (supports net 8, 9, 10):
image

var frameworks = msbuildOutput.Properties.TargetFrameworks
.Split(';')
.Where(x => x.StartsWith("net") || x.StartsWith("netstandard"))
.OrderBy(ParseFrameworkVersion)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the parse fails, it returns 0.0, which will come before any valid version. Is that intentional?

{
var frameworks = msbuildOutput.Properties.TargetFrameworks
.Split(';')
.Where(x => x.StartsWith("net") || x.StartsWith("netstandard"))
Copy link
Member

@drewnoakes drewnoakes Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parsing the TargetFramework is not robust. For example, these are all valid values:

  • net9.0
  • net90 (would be considered version 90.0)
  • net9000 (would be considered version 9000.0)
  • net9.0.0.0 (does the version class here support four parts)
  • NET9.0 (would be filtered out by case-sensitive checks earlier)

In this case, it only impacts projects that multi-target.

To do this correctly involves more steps. We need to take each of the values from TargetFrameworks, then call MSBuild again for each. The properties that should be used here are TargetFrameworkIdentifier and TargetFrameworkVersion. These are the "real" values that define what framework the project uses. The TargetFramework is just an alias and can be anything.

For example, given project:

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

  <PropertyGroup>
    <TargetFrameworks>net9.0;netstandard2.1</TargetFrameworks>
  </PropertyGroup>

</Project>

The following command will give you a reliable version:

$ dotnet msbuild -p:TargetFramework="netstandard2.1" -getProperty:"TargetFrameworkIdentifier;TargetFrameworkVersion" MyProject.csproj
{
  "Properties": {
    "TargetFrameworkIdentifier": ".NETStandard",
    "TargetFrameworkVersion": "v2.1"
  }
}

$ dotnet msbuild -p:TargetFramework="net9.0" -getProperty:"TargetFrameworkIdentifier;TargetFrameworkVersion" MyProject.csproj
{
  "Properties": {
    "TargetFrameworkIdentifier": ".NETCoreApp",
    "TargetFrameworkVersion": "v9.0"
  }
}

So, I'd recommend keeping the first call as:

$ dotnet msbuild -getProperty:"TargetFramework;TargetFrameworks" MyProject.csproj
{
  "Properties": {
    "TargetFramework": "",
    "TargetFrameworks": "net9.0;netstandard2.1"
  }
}

Then you have the following decisions:

  • If TargetFramework has a value, the project only has one target and you can return it directly.
  • If TargetFrameworks has a single value (which can happen) you can return it directly.
  • Otherwise, split TargetFrameworks and for each, invoke the command passing -p:TargetFramework="<value>" and -getProperty:"TargetFrameworkIdentifier;TargetFrameworkVersion". This will give you pairs of identifier/version values to process. If you want to keep the same logic, you can filter out anything that's not .NETStandard or .NETCoreApp, then order by the parsed versions (removing the leading v).

@drewnoakes
Copy link
Member

In the case that the version is not supported, I think it'd be nice to not show the user a stack trace. Stack traces are usually shown when something internal goes wrong. In this case, the problem is the user input data (their project), and the tooling should handle all kinds of invalid input in as graceful and helpful way as possible.

@haileymck
Copy link
Member Author

In the case that the version is not supported, I think it'd be nice to not show the user a stack trace. Stack traces are usually shown when something internal goes wrong. In this case, the problem is the user input data (their project), and the tooling should handle all kinds of invalid input in as graceful and helpful way as possible.

Ok! I will update to a log and exit instead of a throw here.

@haileymck
Copy link
Member Author

updated so log instead of throw when there is a unsupported target framework in the project. See the description for the updated image of what this will look like

else
{
throw new NotSupportedException($"Target framework '{targetFramework}' is not supported.");
logger?.LogError("Target framework '{TargetFramework}' is not supported. Installing recent release of '{PackageName}'. Consider upgrading your target framework to install a compatible package version.", targetFramework, package.Name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies if I've asked this before, but does this need to be localized?

What does "Installing recent release of ..." mean in this context? I'm not 100% clear on this error message.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants