【问题标题】:Why does MSBuild ignore my BeforePublish target?为什么 MSBuild 会忽略我的 BeforePublish 目标?
【发布时间】:2012-10-05 15:57:03
【问题描述】:

我必须在这里遗漏一些明显的东西,但我在 ASP.NET MVC Web 项目的 .csproj 文件的末尾有这个:

    [...]
    <Target Name="BeforePublish">
        <Error Condition="'foo'=='foo'" Text="test publish error" />
    </Target>
</Project>

据我所知,这总是会导致发布失败并出现错误。但是,如果我加载项目,右键单击它,然后单击“发布”,则该项目会顺利发布。我错过了什么?

【问题讨论】:

  • 如果你从VS2010命令行执行msbuild.exe MyMvcProject.csproj /t:PublishOnly会发生什么?
  • 可能没有这样的目标“BeforePublish”(除非这是您非常自定义的目标)。你想用这个结构覆盖什么确切的目标?
  • @AlexeyShcherbak BeforePublish 目标记录在 this MSDN page 上,并在我的 Microsoft.Common.targets 文件中定义。
  • @SevaTitov 有趣;我收到错误Publish is only valid for 'Windows Application' or 'Console Application' project types. - 所以我猜当您在 Visual Studio 中右键单击 MVC 项目并单击“发布”时,它不使用 MSBuild?是不是我无法真正自定义的 Visual Studio 内置的东西?
  • Visual Studio 很可能直接调用 MSBuild 自定义任务(程序集),因此很遗憾似乎没有办法拦截发布“目标”。 Before/AfterBuild 似乎是唯一的选择。

标签: visual-studio-2010 msbuild


【解决方案1】:

我最终得出的答案适用于 Visual Studio 2010 和 Visual Studio 2012;把它放在你的 web 应用程序的 .csproj 文件的末尾之前:

<Project...
    [...]
    <!-- The following makes sure we can't accidentally publish a non-Release configuration from within Visual Studio -->
    <Target Name="PreventNonReleasePublish2010" BeforeTargets="PipelinePreDeployCopyAllFilesToOneFolder" Condition="'$(BuildingInsideVisualStudio)'=='true' AND '$(VisualStudioVersion)'=='10.0'">
        <Error Condition="'$(Configuration)'!='Release'" Text="When publishing from Visual Studio 2010, you must publish the Release configuration!" />
    </Target>
    <Target Name="PreventNonReleasePublish2012" BeforeTargets="MSDeployPublish" Condition="'$(BuildingInsideVisualStudio)'=='true' AND '$(VisualStudioVersion)'=='11.0'">
        <Error Condition="'$(Configuration)'!='Release'" Text="When publishing from Visual Studio 2012, you must publish the Release configuration!" />
    </Target>
</Project>

继续阅读以了解我在此答案背后的想法,但基本上它围绕这样一个事实,即 Visual Studio 2010 定义了要连接的 PipelinePreDeployCopyAllFilesToOneFolder 目标,而 Visual Studio 2012 定义了更“标准”的 MSDeployPublish 目标上钩。

上述代码仅允许在 Visual Studio 中的 Release 配置中部署发布,但可以轻松修改它以阻止 所有从 Visual Studio 中部署发布。

AFAIR,Visual Studio 2010 上下文菜单中的“发布”调用 webdeploy\msdeploy 工具。我玩了一点,但我一点也不喜欢。如果您仍想使用此功能并将目标插入某处 - 您需要知道确切的目标及其依赖属性。

检查 c:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets

您会发现两个任务 - MSDeploy 和 VSMSDeploy。后一个听起来很适合我。这个文件中根本没有使用第一个。但是 VSMSDeploy 在三个不同的目标中使用, PackageUsingManifest、TestDeployPackageToLocal 和 MSDeployPublish。后一个听起来不错;)

<Target Name="MSDeployPublish" DependsOnTargets="$(MSDeployPublishDependsOn)">

所以你只需要覆盖一个属性。将它放在您的目标之前,“YourTargetName”将在 MSDeployPublish 之前被调用。

<PropertyGroup>
    <MSDeployPublishDependsOn Condition="'$(MSDeployPublishDependsOn)'!=''">
        $(MSDeployPublishDependsOn);
        YourTargetName;
    </MSDeployPublishDependsOn>
  </PropertyGroup>

如果您已经切换到 MSBuild 4.0,则有一种更简单的方法来挂钩您的目标。您只需要指定BeforeTarget 属性。在我们的例子中,它将是这样的:

  <Target Name="MyTarget" BeforeTargets="MSDeployPublish">
        <Error Condition="'foo'=='foo'" Text="test publish error" />
  </Target>

我希望这会有所帮助。询问您是否还有其他问题。

PS:我没有检查所有这些,因为我没有任何支持 MSDeploy 的环境;)

注意:我记得我不鼓励将 MSDeploy 用于我们自己的产品,因为为continuous integration (CI) 系统正确配置它是非常违反直觉的。也许我不是很擅长,你的解决方案会正常工作。但请谨慎使用 MSDeploy。

【讨论】:

  • 首先,Intellisense 告诉我 BeforeTargets 而不是 BeforeTarget 作为 Target 属性。其次,不幸的是,添加它并没有奏效。它仍然可以发布。 :-(
  • 对,好像我不小心擦掉了一个字母 =(。属性名称应该是 BeforeTargets。我刚刚测试过,我的控制台有发布错误“测试发布错误”。habrastorage.org/storage2/5a1/d4e/553/…在主要答案中修复
  • 是的,但即使我使用BeforeTargets 属性,它也不会改变任何东西。它仍在发布。
  • 使用 这个提示来自这个问题(你也可以投票赞成它的用处;)):stackoverflow.com/questions/3297194/…
  • 我回答你的问题了吗?
【解决方案2】:

不确定它是否可以在 VS 2010 中工作,因为我只在 VS 2012 中对此进行了测试,但我发现将目标放在 (ProjectDir)/Properties/PublishProfiles/(ProfileName).pubxml 文件中作为“AfterBuild”目标有效。例如,它不会在您构建项目时触发,但会在您发布项目时触发。

所以不要放

<Target Name="BeforePublish">
    <Error Condition="'foo'=='foo'" Text="test publish error" />
</Target>

在您的 .csproj 文件中,尝试放入

<Target Name="AfterBuild">
    <Error Condition="'foo'=='foo'" Text="test publish error" />
</Target>

改为在您的 .pubxml 文件中,它应该在发布之前触发。

【讨论】:

  • 赞成,因为这个答案展示了一种使用事件定义封装事件的技术,该技术特定于特定的发布配置文件(而不是将其推送到主项目文件中)。
【解决方案3】:

在我的项目文件中,默认情况下被注释掉,我不小心在 cmets 中添加了一个新的,因此它没有被调用。愚蠢的错误。

之后,我获得了在 Visual Studio 2010 中工作的 BeforePublish 目标。

<Target Name="BeforePublish">
 //insert awesome here
 </Target>

注意:你必须提供你自己的真棒:)

【讨论】:

  • 第一句的前半部分看不懂。你能解决它吗?
猜你喜欢
  • 1970-01-01
  • 2012-12-11
  • 1970-01-01
  • 1970-01-01
  • 2017-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多