I installed VS 2019 Pro and tried to compile our solution just to get this:
error MSB4226: The imported project "C:\Program Files (x86)\Microsoft
Visual Studio\2019\Professional\MSBuild\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets" was not found. Also, tried
to find "WebApplications\Microsoft.WebApplication.targets" in the fallback search path(s) for $(VSToolsPath) - "C:\Program Files (x86)\MSBuild\Mi
crosoft\VisualStudio\v15.0" . These search paths are defined in "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\
Bin\MSBuild.exe.Config". Confirm that the path in the <Import> declaration is correct, and that the file exists on disk in one of the search paths
Here is why it happens:
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.VisualStudioVersion.v*.Common.props" Condition="'$(VSToolsPath)' == ''" />
MSBuildExtensionsPath = C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild
MSBuildToolsVersion = Current
$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)
indeed exists, see below.$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)
:
C:\> dir "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current"
Directory: C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 6/13/2019 9:11 PM Bin
d----- 5/27/2019 4:42 PM Imports
d----- 5/27/2019 4:41 PM Microsoft.Common.targets
d----- 5/27/2019 4:42 PM SolutionFile
-a---- 5/27/2019 4:38 PM 13606 Microsoft.Common.props
-a---- 5/27/2019 4:38 PM 789 Microsoft.VisualStudioVersion.v15.Common.props
-a---- 5/27/2019 4:38 PM 2029 THIRDPARTYNOTICES.txt
C:\>
So, VS 2019 actually loads Microsoft.VisualStudioVersion.v15.Common.props
. And what is inside? Observe:
C:\> cat "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Microsoft.VisualStudioVersion.v15.Common.props"
<!--
***********************************************************************************************
Microsoft.VisualStudio.v15.Common.props
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.
Copyright (C) Microsoft Corporation. All rights reserved.
***********************************************************************************************
-->
<Project>
<PropertyGroup>
<VisualStudioVersion>15.0</VisualStudioVersion>
<VSToolsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
</Project>
C:\>
So, at the end VSToolsPath
is C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Microsoft\VisualStudio\v15.0
which is obviously wrong, because no such directory exists. What does exist is v16.0.
Anyway, it seems the root cause for all of this is c:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild
communicates to the world that MSBuild 15 is version to be used instead of MSBuild 16.
What am I missing?
Our projects all include the following import statement:
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.VisualStudioVersion.v*.Common.props" Condition="'$(VSToolsPath)' == ''" />
I guess the root cause of the issue is that you put the statement above the definition of VSToolsPath
property.
Create a simple asp.net web application(.net framework) in VS2019 and its structure looks like this:
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
...
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
...
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
...
</PropertyGroup>
<ItemGroup>
...
</ItemGroup>
<!--Position 1-->
<!--<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.VisualStudioVersion.v*.Common.props" Condition="'$(VSToolsPath)' == ''" />--> <!--Position 1-->
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> <!--This is where the VSToolsPath is defined.-->
</PropertyGroup>
<!--Position 2-->
<!--<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.VisualStudioVersion.v*.Common.props" Condition="'$(VSToolsPath)' == ''" />--> <!--Position 2-->
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" /> <!--This is where the error finally occurs.-->
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
<ProjectExtensions>
...
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. ...-->
</Project>
I assume you may add the statement in the top of the xx.csproj file or somewhere above the
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
If so, since now $(VSToolsPath) is not defined yet. Its value is empty, then the build system will execute the Import element in your statement to Import $(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.VisualStudioVersion.v*.Common.props
file, which will then result in the VisualStudioVersion
property be set 15.0 instead of 16.0.
And since it import properties from Microsoft.VisualStudioVersion.v15.Common.props
, the VSToolsPath
is now set as $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0
, and this will cause the final error you get since the part of the path to Microsoft.WebApplication.targets
file is $(VSToolsPath). See:
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" /> <!--This is where the error finally occurs.-->
So if you add your statement above the first definition of $(VSToolsPath) like position 1, you'll get this error. If you add your statement below the definition of $(VSToolsPath) and above the Import of Microsoft.WebApplication.targets
like position 2, all works well.
Update1:
About the info of Import element see this document. imported projects are inspected in the order that they are imported.
Update2:
Hint from mark, I post an issue in msbuild. The link.
For me, the following worked.
In the csproj file,
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets" />
is replaced with
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With