首页 > 解决方案 > ASP.NET Web 项目模板包含 2 个用于导入 Microsoft.WebApplication.targets $VSToolsPath) 与 $(MSBuildExtensionsPath32) 的条目

问题描述

在撰写本文时,我正在使用 Visual Studio 2017 (ver15.6.6) 和 .NET Framework ver4.7.02558 (MSBuild ver15.5.x),即最新更新。当我使用默认模板创建 ASP.NET Web 项目时,生成的 .csproj 文件包含以下代码段:

<PropertyGroup>
  <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
  <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
[...]
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />

如您所见,Microsoft.WebApplication.targets 被导入了两次。我在 .csproj 的这个块上摸不着头脑:

出于测试目的,我注释掉了第一个语句并启用了第二个语句,如下所示:

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets" Condition="true" />

这似乎在我的开发机器和我们拥有的无头 CI 服务器中都可以正常工作。我之所以提到这一点,是因为如果使用默认的 \v10.0\,那么构建系统会以一种非常深奥的方式中断:

在我们的 CI 服务器中,网络发布机制静默地无法在输出文件夹中生成任何内容,同时它也不会产生任何错误(哎呀!)。

这是一个已知问题,似乎影响了许多用户。在此处查看 rianjs 的答案:

https://github.com/Microsoft/msbuild/issues/1901

他得出了和我一样的结论。我无法理解为什么 VS17 的默认模板没有内置规定来解决默认构建系统中的这些微妙之处,如上图所示。

.csproj 的所有这些默认设置似乎都离我们很远,完全具有误导性,并且构成了各种奇怪、无声和难以弄清楚的错误的电池。尤其是在 CI 服务器方面。

为了使用默认模板解决这些问题,我是否需要通过插件或其他东西分别更新 Visual Studio 的模板以获得 VS17 的健康模板?这里发生了什么?

标签: c#asp.netvisual-studiomsbuildweb-publishing

解决方案


ASP.NET Web 项目模板包含 2 个用于导入 Microsoft.WebApplication.targets $VSToolsPath) 与 $(MSBuildExtensionsPath32) 的条目

解决这个问题并不容易,因为这个问题的原因有很多,服务器环境,Visual Studio 扩展,一些 nuget 包等等。我想提供一些关于这个问题的想法。

根据您的描述,如果您将第一条语句注释掉并启用第二条语句,您就可以在构建服务器上构建成功。因此,似乎VSToolsPath在第一条语句中不起作用的变量。

当我们用记事本打开项目文件 .csproj 时,我们将看到以下导入:

  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />

您可以使用默认模板成功构建,<Import Project="...\v15.0\WebApplications\Microsoft.WebApplication.targets" Condition="true" />但使用默认模板失败,显然,$(VSToolsPath)第一条语句中的值不正确或为空,而 的值$(VSToolsPath)取决于 的值$(VisualStudioVersion)。在$(VisualStudioVersion)文件中定义Microsoft.VisualStudioVersion.v15.Common.props

  <PropertyGroup>
    <VisualStudioVersion>15.0</VisualStudioVersion>
    <VSToolsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>

</Project>

该文件的位置:C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0

所以,如果第一条语句没有正确导入,

首先,请检查文件是否Microsoft.VisualStudioVersion.v15.Common.props存在于您的构建服务器上

其次,检查您是否从 Visual Studio 2017 调用 MSBuild C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin:.

第三,检查您是否在项目中安装了任何其他 nuget,例如 Microsoft.VSSDK.BuildTools、Visual Studio 2017 扩展 - VSToolsPath not working

如果以上所有内容都对您没有帮助,一种解决方法是使用以下语句创建自定义项目模板:

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets" Condition="true" />

希望这可以帮助。


推荐阅读