Skip to content

[Bug]: Project object can no longer be created if the change wave 17.10 is in use. #9869

Closed as not planned
@MarkKharitonov

Description

@MarkKharitonov

Issue Description

Consider the following code:

using Microsoft.Build.Evaluation;
using Microsoft.Build.Locator;

internal class Program
{
    private static void Main(string[] args)
    {
        Environment.SetEnvironmentVariable("MSBUILDDISABLEFEATURESFROMVERSION", new Version(17, 10).ToString());
        var msbuildDir = GetMSBuildDir();

        if (string.IsNullOrEmpty(msbuildDir))
        {
            MSBuildLocator.RegisterDefaults();
        }
        else
        {
            MSBuildLocator.RegisterMSBuildPath(msbuildDir);
        }
        Run(SLN_DIR_PATH, SLN_DIR_PATH + CSPROJ_REL_PATH);
    }

    private static void Run(string slnDirPath, string csprojPath)
    {
        new Project(csprojPath, new Dictionary<string, string>
        {
            ["SolutionDir"] = Path.GetDirectoryName(slnDirPath) + "\\"
        }, null);
    }

    private static string? GetMSBuildDir()
    {
        var vsInstallDir = Environment.GetEnvironmentVariable("VSINSTALLDIR");
        if (vsInstallDir == null)
        {
            vsInstallDir = Environment.GetEnvironmentVariable("VSAPPIDDIR");
            if (!string.IsNullOrEmpty(vsInstallDir))
            {
                vsInstallDir = Path.GetFullPath(vsInstallDir + "\\..\\..\\");
            }
        }
        if (!string.IsNullOrEmpty(vsInstallDir))
        {
            vsInstallDir += "MSBuild\\Current\\Bin\\";
        }

        return vsInstallDir;
    }
}

And assume SLN_DIR_PATH + CSPROJ_REL_PATH point at an existing csproj file with a solution file inside SLN_DIR_PATH.

When I run this code - it succeeds. However, if I comment the MSBUILDDISABLEFEATURESFROMVERSION line, then it fails with the following exception:

Microsoft.Build.Exceptions.InvalidProjectFileException
  HResult=0x80131500
  Message=The SDK resolver assembly "C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\SdkResolvers\Microsoft.DotNet.MSBuildSdkResolver\Microsoft.DotNet.MSBuildSdkResolver.dll" could not be loaded. Could not load file or assembly 'Microsoft.DotNet.MSBuildSdkResolver, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.  C:\dayforce\CSTool\scratch\scratch.csproj
  Source=Microsoft.Build
  StackTrace:
   at Microsoft.Build.Shared.ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(Boolean condition, String errorSubCategoryResourceName, BuildEventFileInfo projectFile, Exception innerException, String resourceName, Object[] args)
   at Microsoft.Build.Shared.ProjectFileErrorUtilities.ThrowInvalidProjectFile(BuildEventFileInfo projectFile, Exception innerException, String resourceName, Object[] args)
   at Microsoft.Build.BackEnd.SdkResolution.SdkResolverLoader.LoadResolvers(String resolverPath, ElementLocation location, List`1 resolvers)
   at Microsoft.Build.BackEnd.SdkResolution.SdkResolverLoader.LoadResolversFromManifest(SdkResolverManifest manifest, ElementLocation location)
   at Microsoft.Build.BackEnd.SdkResolution.CachingSdkResolverLoader.<>n__0(SdkResolverManifest manifest, ElementLocation location)
   at Microsoft.Build.BackEnd.SdkResolution.CachingSdkResolverLoader.<>c__DisplayClass10_0.<LoadResolversFromManifest>b__0(SdkResolverManifest manifest)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.Build.BackEnd.SdkResolution.CachingSdkResolverLoader.LoadResolversFromManifest(SdkResolverManifest manifest, ElementLocation location)
   at Microsoft.Build.BackEnd.SdkResolution.SdkResolverService.GetResolvers(IList`1 resolversManifests, LoggingContext loggingContext, ElementLocation sdkReferenceLocation)
   at Microsoft.Build.BackEnd.SdkResolution.SdkResolverService.ResolveSdkUsingResolversWithPatternsFirst(Int32 submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, String solutionPath, String projectPath, Boolean interactive, Boolean isRunningInVisualStudio, Boolean failOnUnresolvedSdk)
   at Microsoft.Build.BackEnd.SdkResolution.SdkResolverService.ResolveSdk(Int32 submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, String solutionPath, String projectPath, Boolean interactive, Boolean isRunningInVisualStudio, Boolean failOnUnresolvedSdk)
   at Microsoft.Build.BackEnd.SdkResolution.CachingSdkResolverService.<>n__0(Int32 submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, String solutionPath, String projectPath, Boolean interactive, Boolean isRunningInVisualStudio, Boolean failOnUnresolvedSdk)
   at Microsoft.Build.BackEnd.SdkResolution.CachingSdkResolverService.<>c__DisplayClass3_0.<ResolveSdk>b__2()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at Microsoft.Build.BackEnd.SdkResolution.CachingSdkResolverService.ResolveSdk(Int32 submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, String solutionPath, String projectPath, Boolean interactive, Boolean isRunningInVisualStudio, Boolean failOnUnresolvedSdk)
   at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImportsFromUnescapedImportExpressionConditioned(String directoryOfImportingFile, ProjectImportElement importElement, List`1& projects, SdkResult& sdkResult)
   at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImports(String directoryOfImportingFile, ProjectImportElement importElement, SdkResult& sdkResult)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.Evaluate()
   at Microsoft.Build.Evaluation.Evaluator`4.Evaluate(IEvaluatorData`4 data, Project project, ProjectRootElement root, ProjectLoadSettings loadSettings, Int32 maxNodeCount, PropertyDictionary`1 environmentProperties, ILoggingService loggingService, IItemFactory`2 itemFactory, IToolsetProvider toolsetProvider, IDirectoryCacheFactory directoryCacheFactory, ProjectRootElementCacheBase projectRootElementCache, BuildEventContext buildEventContext, ISdkResolverService sdkResolverService, Int32 submissionId, EvaluationContext evaluationContext, Boolean interactive)
   at Microsoft.Build.Evaluation.Project.ProjectImpl.Reevaluate(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings, EvaluationContext evaluationContext)
   at Microsoft.Build.Evaluation.Project.ProjectImpl.ReevaluateIfNecessary(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings, EvaluationContext evaluationContext)
   at Microsoft.Build.Evaluation.Project.ProjectImpl.ReevaluateIfNecessary(ILoggingService loggingServiceForEvaluation, EvaluationContext evaluationContext)
   at Microsoft.Build.Evaluation.Project.ProjectImpl.ReevaluateIfNecessary(EvaluationContext evaluationContext)
   at Microsoft.Build.Evaluation.Project.ProjectImpl.Initialize(IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectLoadSettings loadSettings, EvaluationContext evaluationContext, Boolean interactive)
   at Microsoft.Build.Evaluation.Project..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectCollection projectCollection, ProjectLoadSettings loadSettings, EvaluationContext evaluationContext, IDirectoryCacheFactory directoryCacheFactory, Boolean interactive)
   at Microsoft.Build.Evaluation.Project..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectCollection projectCollection, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.Project..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, ProjectCollection projectCollection, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.Project..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, ProjectCollection projectCollection)
   at Microsoft.Build.Evaluation.Project..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion)
   at Program.Run(String slnDirPath, String csprojPath) in C:\dayforce\CSTool\scratch\Program.cs:line 24
   at Program.Main(String[] args) in C:\dayforce\CSTool\scratch\Program.cs:line 19

  This exception was originally thrown at this call stack:
    System.Reflection.RuntimeAssembly.InternalLoad(System.Reflection.AssemblyName, ref System.Threading.StackCrawlMark, System.Runtime.Loader.AssemblyLoadContext, System.Reflection.RuntimeAssembly, bool)
    System.Reflection.Assembly.Load(System.Reflection.AssemblyName)
    Microsoft.Build.BackEnd.SdkResolution.SdkResolverLoader.LoadResolverAssembly(string)
    Microsoft.Build.BackEnd.SdkResolution.SdkResolverLoader.LoadResolvers(string, Microsoft.Build.Construction.ElementLocation, System.Collections.Generic.List<Microsoft.Build.Framework.SdkResolver>)

Inner Exception 1:
FileNotFoundException: Could not load file or assembly 'Microsoft.DotNet.MSBuildSdkResolver, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.

Steps to Reproduce

scratch.zip
msbuild.zip

Since the binary log is small and without any secrets, I just renamed msbuild.binlog to msbuild.,zip and uploaded here.

To show the issue pass the 3rd parameter exp.

Good run

C:\scratch> .\bin\Debug\net8.0\scratch.exe . .\scratch.csproj
C:\scratch>

Bad run

C:\scratch> .\bin\Debug\net8.0\scratch.exe . .\scratch.csproj exp
Unhandled exception. Microsoft.Build.Exceptions.InvalidProjectFileException: The SDK resolver assembly "C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\SdkResolvers\Microsoft.DotNet.MSBuildSdkResolver\Microsoft.DotNet.MSBuildSdkResolver.dll" could not be loaded. Could not load file or assembly 'Microsoft.DotNet.MSBuildSdkResolver, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.  C:\dayforce\CSTool\scratch\scratch.csproj
 ---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.DotNet.MSBuildSdkResolver, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
File name: 'Microsoft.DotNet.MSBuildSdkResolver, Culture=neutral, PublicKeyToken=null'
   at System.Reflection.RuntimeAssembly.InternalLoad(AssemblyName assemblyName, StackCrawlMark& stackMark, AssemblyLoadContext assemblyLoadContext, RuntimeAssembly requestingAssembly, Boolean throwOnFileNotFound)
   at System.Reflection.Assembly.Load(AssemblyName assemblyRef)
   at Microsoft.Build.BackEnd.SdkResolution.SdkResolverLoader.LoadResolverAssembly(String resolverPath)
   at Microsoft.Build.BackEnd.SdkResolution.SdkResolverLoader.LoadResolvers(String resolverPath, ElementLocation location, List`1 resolvers)
   --- End of inner exception stack trace ---
   at Microsoft.Build.Shared.ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(Boolean condition, String errorSubCategoryResourceName, BuildEventFileInfo projectFile, Exception innerException, String resourceName, Object[] args)
   at Microsoft.Build.Shared.ProjectFileErrorUtilities.ThrowInvalidProjectFile(BuildEventFileInfo projectFile, Exception innerException, String resourceName, Object[] args)
   at Microsoft.Build.BackEnd.SdkResolution.SdkResolverLoader.LoadResolvers(String resolverPath, ElementLocation location, List`1 resolvers)
   at Microsoft.Build.BackEnd.SdkResolution.SdkResolverLoader.LoadResolversFromManifest(SdkResolverManifest manifest, ElementLocation location)
   at Microsoft.Build.BackEnd.SdkResolution.CachingSdkResolverLoader.<>n__0(SdkResolverManifest manifest, ElementLocation location)
   at Microsoft.Build.BackEnd.SdkResolution.CachingSdkResolverLoader.<>c__DisplayClass10_0.<LoadResolversFromManifest>b__0(SdkResolverManifest manifest)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Microsoft.Build.BackEnd.SdkResolution.CachingSdkResolverLoader.LoadResolversFromManifest(SdkResolverManifest manifest, ElementLocation location)
   at Microsoft.Build.BackEnd.SdkResolution.SdkResolverService.GetResolvers(IList`1 resolversManifests, LoggingContext loggingContext, ElementLocation sdkReferenceLocation)
   at Microsoft.Build.BackEnd.SdkResolution.SdkResolverService.ResolveSdkUsingResolversWithPatternsFirst(Int32 submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, String solutionPath, String projectPath, Boolean interactive, Boolean isRunningInVisualStudio, Boolean failOnUnresolvedSdk)
   at Microsoft.Build.BackEnd.SdkResolution.SdkResolverService.ResolveSdk(Int32 submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, String solutionPath, String projectPath, Boolean interactive, Boolean isRunningInVisualStudio, Boolean failOnUnresolvedSdk)
   at Microsoft.Build.BackEnd.SdkResolution.CachingSdkResolverService.<>n__0(Int32 submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, String solutionPath, String projectPath, Boolean interactive, Boolean isRunningInVisualStudio, Boolean failOnUnresolvedSdk)
   at Microsoft.Build.BackEnd.SdkResolution.CachingSdkResolverService.<>c__DisplayClass3_0.<ResolveSdk>b__2()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at Microsoft.Build.BackEnd.SdkResolution.CachingSdkResolverService.ResolveSdk(Int32 submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, String solutionPath, String projectPath, Boolean interactive, Boolean isRunningInVisualStudio, Boolean failOnUnresolvedSdk)
   at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImportsFromUnescapedImportExpressionConditioned(String directoryOfImportingFile, ProjectImportElement importElement, List`1& projects, SdkResult& sdkResult)
   at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImports(String directoryOfImportingFile, ProjectImportElement importElement, SdkResult& sdkResult)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.Evaluate()
   at Microsoft.Build.Evaluation.Evaluator`4.Evaluate(IEvaluatorData`4 data, Project project, ProjectRootElement root, ProjectLoadSettings loadSettings, Int32 maxNodeCount, PropertyDictionary`1 environmentProperties, ILoggingService loggingService, IItemFactory`2 itemFactory, IToolsetProvider toolsetProvider, IDirectoryCacheFactory directoryCacheFactory, ProjectRootElementCacheBase projectRootElementCache, BuildEventContext buildEventContext, ISdkResolverService sdkResolverService, Int32 submissionId, EvaluationContext evaluationContext, Boolean interactive)
   at Microsoft.Build.Evaluation.Project.ProjectImpl.Reevaluate(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings, EvaluationContext evaluationContext)
   at Microsoft.Build.Evaluation.Project.ProjectImpl.ReevaluateIfNecessary(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings, EvaluationContext evaluationContext)
   at Microsoft.Build.Evaluation.Project.ProjectImpl.ReevaluateIfNecessary(ILoggingService loggingServiceForEvaluation, EvaluationContext evaluationContext)
   at Microsoft.Build.Evaluation.Project.ProjectImpl.ReevaluateIfNecessary(EvaluationContext evaluationContext)
   at Microsoft.Build.Evaluation.Project.ProjectImpl.Initialize(IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectLoadSettings loadSettings, EvaluationContext evaluationContext, Boolean interactive)
   at Microsoft.Build.Evaluation.Project..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectCollection projectCollection, ProjectLoadSettings loadSettings, EvaluationContext evaluationContext, IDirectoryCacheFactory directoryCacheFactory, Boolean interactive)
   at Microsoft.Build.Evaluation.Project..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectCollection projectCollection, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.Project..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, ProjectCollection projectCollection, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.Project..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, ProjectCollection projectCollection)
   at Microsoft.Build.Evaluation.Project..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion)
   at Program.Run(String slnDirPath, String csprojPath) in C:\dayforce\CSTool\scratch\Program.cs:line 54
   at Program.Main(String[] args) in C:\dayforce\CSTool\scratch\Program.cs:line 48
C:\scratch>

Expected Behavior

The code succeeds without disabling the latest change wave.

Actual Behavior

The code fails.

Analysis

No response

Versions & Configurations

See the attached msbuild binary log, but here it is:

C:\scratch> msbuild --version
MSBuild version 17.9.5+33de0b227 for .NET Framework
17.9.5.7608
C:\scratch>

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions