dotnet / msbuild

The Microsoft Build Engine (MSBuild) is the build platform for .NET and Visual Studio.
https://docs.microsoft.com/visualstudio/msbuild/msbuild
MIT License
5.24k stars 1.35k forks source link

InvalidProjectFileException after upgrading VS2017 to 15.8.0 with Microsoft.Build NuGet 15.6.82 #3634

Open jzielnik opened 6 years ago

jzielnik commented 6 years ago

Steps to reproduce

Using Microsoft.Build package (from NuGet in version 15.6.82) added as NuGet reference to a project. Calling constructor of: Microsoft.Build.Evaluation.Project(projectFile) in one of methods. Results in throwing Microsoft.Build.Exceptions.InvalidProjectFileException Stack Trace:

[ERROR] Invalid static method invocation syntax: "[Microsoft.Build.Utilities.ToolLocationHelper]::GetPathToStandardLibraries($(TargetFrameworkIdentifier), $(TargetFrameworkVersion), $(TargetFrameworkProfile), $(PlatformTarget), $(TargetFrameworkRootPath), $(TargetFrameworkFallbackSearchPaths))". Method 'Microsoft.Build.Utilities.ToolLocationHelper.GetPathToStandardLibraries' not found. Static method invocation should be of the form: $([FullTypeName]::Method()), e.g. $([System.IO.Path]::Combine(`a`, `b`)).   C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets
   at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject(String errorSubCategoryResourceName, IElementLocation elementLocation, String resourceName, Object[] args)
   at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject[T1,T2](IElementLocation elementLocation, String resourceName, T1 arg0, T2 arg1)
   at Microsoft.Build.Evaluation.Expander`2.Function`1.Execute(Object objectInstance, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation)
   at Microsoft.Build.Evaluation.Expander`2.PropertyExpander`1.ExpandPropertyBody(String propertyBody, Object propertyValue, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties)
   at Microsoft.Build.Evaluation.Expander`2.PropertyExpander`1.ExpandPropertiesLeaveTypedAndEscaped(String expression, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties)
   at Microsoft.Build.Evaluation.Expander`2.PropertyExpander`1.ExpandPropertiesLeaveEscaped(String expression, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties)
   at Microsoft.Build.Evaluation.Expander`2.ExpandIntoStringLeaveEscaped(String expression, ExpanderOptions options, IElementLocation elementLocation)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluatePropertyElement(ProjectPropertyElement propertyElement)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluatePropertyGroupElement(ProjectPropertyGroupElement propertyGroupElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   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.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   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.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.Evaluate(ILoggingService loggingService, BuildEventContext buildEventContext)
   at Microsoft.Build.Evaluation.Project.Reevaluate(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.Project.ReevaluateIfNecessary(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.Project.Initialize(IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectLoadSettings loadSettings)
   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)

Unfortunately, because product is already released it's hard to fix existing issue. Users who updated their VS2017 to version 15.8.0+ will suffer from not being able to use product.

Is there any workaround?

Expected behavior

Using this constructor should be backward compatible even if user has Microsoft.Build in version older than 15.8.X

Actual behavior

Throws an exception because usage of newly added method which was not present in older version.

Environment data

MSBuild version: Microsoft (R) Build Engine version 15.8.166+gd4e8d81a88 for .NET Framework Copyright (C) Microsoft Corporation. All rights reserved.

15.8.166.59604

VS2017 version: Version 15.8.1

rainersigwald commented 6 years ago

We recommend that you use the Microsoft.Build.Locator package to avoid this and other mismatched-engine-and-targets problems. There is documentation available at https://docs.microsoft.com/en-us/visualstudio/msbuild/updating-an-existing-application.

The only workaround I can think of is to copy the higher version of MSBuild assemblies over the lower version redistributed with your application. That's a pain but has worked before.

tobyash86 commented 6 years ago

I am experiencing the same issue. Isn't it a problem with versioning policy that minor releases are introducing breaking changes? It makes Microsoft.Build API not reliable. Currently, there are many updates for VS which are released really often, should I expect that each of them can break my integration with Microsoft.Build?

@rainersigwald Microsoft.Build.Locator has limitations - strongest of them is lack of compability with Microsoft.Build.* assemblies (older version of them required by my solution which has some projects targeted to pre-4.6 .NET Framework). Also, to my best knowledge Microsoft.Build.Locator works properly only with VS/BuildTools 15.x. Requirement for me is version 11.0+. Also, copying assemblies is not the case as well, because there are conflicts between dependant assemblies versions (e.g. System.Collections.Immutable is commonly used as a reference in my pre-4.6 projects).

Is there any other solution? Is there at least a way to downgrade to 15.7 after 15.8 was installed?

chm-tm commented 6 years ago

@tobyash86: See https://docs.microsoft.com/en-us/visualstudio/productinfo/installing-an-earlier-release-of-vs2017. This does not cover the Express edition.

tobyash86 commented 6 years ago

Thanks @chm-tm, although I had hope that there is an easier way to do this.

chm-tm commented 6 years ago

Since I only depend on Visual Studio 15.8, a.k.a latest-greatest, I could resolve the issue by updating the NuGet packages from from 15.6.82 to 15.8.166. There is still a pit-fall here: We use Professional and Express, which led to different binding redirects. In my case of a project targeting .NET 4.6.1, for System.IO.Compression and System.Runtime.InteropServices.RuntimeInformation. So, this is clearly less robust than the recommended Microsoft.Build.Locator way.

Vance-Smith commented 6 years ago

So the lesson here is do not trust Visual Studio upgrades!?