How to load .NET 6 project in a .NET 6 console application

Viewed 39

I am attempting to load a .NET 6 project (SDK Style) in a .NET 6 console application. My entire project is fairly simple - it actually attempts to load its own .csproj file when it runs from the default output folder:

using Microsoft.Build.Evaluation;

namespace ProjLoading
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var projectLocation = "../../../ProjLoading.csproj";
            var project = new Project(projectLocation, null, null, new ProjectCollection());
        }
    }
}

I am using the following nuget packages:

  • Microsoft.Build (17.2.0)
  • Microsoft.Build.Utilities.Core (17.2.0)

When I run the code, I get the following exception:

Microsoft.Build.Exceptions.InvalidProjectFileException: 'The SDK 'Microsoft.NET.Sdk' specified could not be found.  C:\Users\vchel\source\repos\ProjLoading\ProjLoading\ProjLoading.csproj'

This exception was originally thrown at this call stack:
    Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject(string, Microsoft.Build.Shared.IElementLocation, string, object[])
    Microsoft.Build.Evaluation.Evaluator<P, I, M, D>.ExpandAndLoadImportsFromUnescapedImportExpressionConditioned(string, Microsoft.Build.Construction.ProjectImportElement, out System.Collections.Generic.List<Microsoft.Build.Construction.ProjectRootElement>, out Microsoft.Build.BackEnd.SdkResolution.SdkResult, bool)
    Microsoft.Build.Evaluation.Evaluator<P, I, M, D>.ExpandAndLoadImports(string, Microsoft.Build.Construction.ProjectImportElement, out Microsoft.Build.BackEnd.SdkResolution.SdkResult)
    Microsoft.Build.Evaluation.Evaluator<P, I, M, D>.EvaluateImportElement(string, Microsoft.Build.Construction.ProjectImportElement)
    Microsoft.Build.Evaluation.Evaluator<P, I, M, D>.PerformDepthFirstPass(Microsoft.Build.Construction.ProjectRootElement)
    Microsoft.Build.Evaluation.Evaluator<P, I, M, D>.Evaluate()
    Microsoft.Build.Evaluation.Project.ProjectImpl.Reevaluate(Microsoft.Build.BackEnd.Logging.ILoggingService, Microsoft.Build.Evaluation.ProjectLoadSettings, Microsoft.Build.Evaluation.Context.EvaluationContext)
    Microsoft.Build.Evaluation.Project.ProjectImpl.ReevaluateIfNecessary(Microsoft.Build.BackEnd.Logging.ILoggingService, Microsoft.Build.Evaluation.ProjectLoadSettings, Microsoft.Build.Evaluation.Context.EvaluationContext)
    Microsoft.Build.Evaluation.Project.ProjectImpl.Initialize(System.Collections.Generic.IDictionary<string, string>, string, string, Microsoft.Build.Evaluation.ProjectLoadSettings, Microsoft.Build.Evaluation.Context.EvaluationContext)
    Microsoft.Build.Evaluation.Project.Project(string, System.Collections.Generic.IDictionary<string, string>, string, string, Microsoft.Build.Evaluation.ProjectCollection, Microsoft.Build.Evaluation.ProjectLoadSettings, Microsoft.Build.Evaluation.Context.EvaluationContext, Microsoft.Build.FileSystem.IDirectoryCacheFactory)
    ...
    [Call Stack Truncated]

I am building/running this console application from Visual Studio 2022 (17.2.2).

How can I solve this problem?

1 Answers

I don't understand why, but I ran across this solution and it has solved the problem:

https://blog.rsuter.com/missing-sdk-when-using-the-microsoft-build-package-in-net-core/

In case the link dies in the future, my full project now sets the environment variable MSBUILD_EXE_PATH to the latest version of msbuild as shown in the following code:

using Microsoft.Build.Evaluation;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace ProjLoading
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var startInfo = new ProcessStartInfo("dotnet", "--list-sdks")
            {
                RedirectStandardOutput = true
            };

            var process = Process.Start(startInfo);
            process.WaitForExit(1000);

            var output = process.StandardOutput.ReadToEnd();
            var sdkPaths = Regex.Matches(output, "([0-9]+.[0-9]+.[0-9]+) \\[(.*)\\]")
                .OfType<Match>()
                .Select(m => System.IO.Path.Combine(m.Groups[2].Value, m.Groups[1].Value, "MSBuild.dll"));

            var sdkPath = sdkPaths.Last();
            Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", sdkPath);

            var projectLocation = "../../../ProjLoading.csproj";
            var project = new Project(projectLocation, null, null, new ProjectCollection());
        }
    }
}
Related