SuperJMN
SuperJMN

Reputation: 13982

How to get the Target Framework/s of a project (.csproj) using Microsoft.CodeAnalysis (or similar)?

I'm building a .NET tool that needs to query project properties like Target Framework/s. My first thought has been Microsoft.CodeAnalysis.

using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis.MSBuild;

public static class Program
{
    public static async Task Main()
    {
        MSBuildLocator.RegisterDefaults(); 
        using var workspace = MSBuildWorkspace.Create();
        var pr = await workspace.OpenProjectAsync("E:\\Repos\\SuperJMN\\DotNet-Ssh-Deployer\\NetCoreSsh\\DotNetSsh.csproj");
    }
}

I've loaded a project, and I can see a lot of information in the pr instance, but I haven't found anything related to the TFMs.

Upvotes: 0

Views: 1371

Answers (2)

You need to follow the guide provided by Microsoft exactly. Yes, you need Microsoft.Build.Locator; yes, you need to split your code for reasons explained here.

In your csproj (substitute latest package versions):

<ItemGroup>
    <PackageReference Include="Microsoft.Build" Version="17.12.6"
        ExcludeAssets="runtime" />
    <PackageReference Include="Microsoft.Build.Locator" Version="1.7.8" />
    <PackageReference Include="Microsoft.Build.Utilities.Core" Version="17.12.6"
        ExcludeAssets="runtime" />
</ItemGroup>

and Program.cs:

using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis.MSBuild;

public static class Program
{
    public static void Main()
    {
        MSBuildLocator.RegisterDefaults(); 

        PrintTfm();
    }

    static void PrintTfm()
    {
        Project csproj = new(
            @"E:\Repos\SuperJMN\DotNet-Ssh-Deployer\NetCoreSsh\DotNetSsh.csproj");
        var tfmProperty = csproj.GetProperty("TargetFramework");

        // prints something like "net8.0"
        Console.WriteLine(tfmProperty.EvaluatedValue);
    }
}

Note that if you are using Directory.Build.props or another file that can affect the final computed values of project file properties, this program will correctly take that into account! For example, the csproj I provided when testign the above code had no TargetFramework element defined, because it inherits that value from a root-level Directory.Build.props - and the outputted TFM was (correctly) the one defined in the latter file.

Upvotes: 0

Chobo
Chobo

Reputation: 96

You can leverage reflection's Assembly.ImageRuntimeVersion property to grab it.

Here's the documentation on it: https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.imageruntimeversion?redirectedfrom=MSDN&view=net-6.0#System_Reflection_Assembly_ImageRuntimeVersion

Upvotes: 0

Related Questions