【问题标题】:MSBuild: Ensure a target is run before any other build stepsMSBuild:确保在任何其他构建步骤之前运行目标
【发布时间】:2011-11-09 15:53:21
【问题描述】:

我正在尝试在任何其他构建步骤发生之前更新 AssemblyInfo.cs 文件以反映项目的下一个发布版本。

在我的项目文件中我在结束前添加:

<Import Project="$(ProjectDir)Properties\PublishVersion.proj" />

PublishVersion.proj 如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<Target Name="BeforeBuild">
    <FormatVersion Version="$(ApplicationVersion)" Revision="$(ApplicationRevision)">
        <Output TaskParameter="OutputVersion" PropertyName="SetVersion" />
    </FormatVersion>
    <FileUpdate Files="$(ProjectDir)Properties\AssemblyInfo.cs"
       Regex="\d+\.\d+\.\d+\.\d+"
       ReplacementText="$(SetVersion)" />
</Target>
</Project>

现在它确实在构建完成之前在某个地方执行,但绝对不是在它开始之前,因为当我查看生成的 exe 时,它​​有一个在构建开始之前在 AssemblyInfo.cs 中的文件版本,但 .application 文件和清单文件有各种参考新版本。

生成的清单文件(构建开始前为 1.0.0.0,构建后为 1.0.0.4):

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly ...>
  <asmv1:assemblyIdentity name="BHTechSupport.exe" version="1.0.0.4" ... />
  ...
  <entryPoint>
    <assemblyIdentity name="BHTechSupport" version="1.0.0.0" ... />
    ...
  </entryPoint>
  ...
  <dependency>
    <dependentAssembly ... codebase="BHTechSupport.exe" ...>
      <assemblyIdentity name="BHTechSupport" version="1.0.0.0" ... />
      ...
    </dependentAssembly>
  </dependency>
  ...
</asmv1:assembly>

那么我如何确保我的目标在其他一切之前得到执行?

对 PublishVersion.proj 进行更改有时似乎没有生效,我需要清理解决方案并重新启动 Visual Studio 才能生效。

【问题讨论】:

  • 看起来您使用的是 Visual Studio 2010 和 MSBUILD 4.0,对吗?否则BeforeTargets 将不起作用,您必须使用DependsOnTargets
  • 是的,我将如何指定构建目标以依赖于我的目标?
  • 尝试在 PublishVersion.proj 中设置 DefaultTargets="MyTarget"
  • DefaultTargets="MyTarget"InitialTargets="MyTarget" 结果没有差异
  • @sll 将其作为答案,以便我投票。

标签: c# msbuild


【解决方案1】:

也许你必须使用BeforeBuild 目标。

那么我如何确保我的目标在一切之前得到执行 还有吗?

要检查您的目标执行情况,您可以将MSBuild project build output verbosity 更改为Diagnostic。在工具 > 选项 > 项目和解决方案 > 构建和运行下找到它。然后构建项目并在输出窗口中找到您的目标。

对 PublishVersion.proj 进行更改有时似乎不需要 效果,我需要清理解决方案并重新启动 Visual Studio 在生效之前。

AFAIK,Visual Studio 会加载目标文件一次,因此您必须重新加载项目才能看到结果。

更新我不知道您的版本控制系统,但这并不重要。无论如何,我试图为你提供一个简单的例子。

using System;
using System.IO;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;

namespace Foo.Build.Tasks {

    public sealed class GenerateVersion : Task {

        [Output]
        public ITaskItem[] GeneratedFiles { get; private set; }

        public override bool Execute() {
            string objPath = Path.Combine(Path.GetDirectoryName(this.BuildEngine3.ProjectFileOfTaskNode), "obj");
            string path = Path.Combine(objPath, "VersionInfo.cs");

            File.WriteAllText(path, @"using System.Reflection;
[assembly: AssemblyVersion(""2.0.0"")]");

            GeneratedFiles = new[] { new TaskItem(path) };

            return true;
        }

    }

}

前面的任务会生成一个文件,其中包含AssemblyVersion 元数据或您想要的所有内容。

最后,你必须改变你的项目文件如下:

<UsingTask TaskName="Foo.Build.Tasks.GenerateVersion" AssemblyFile="Foo.Build.Tasks.dll" />

<Target Name="BeforeBuild">
  <GenerateVersion>
    <Output TaskParameter="GeneratedFiles" ItemName="Compile" />
  </GenerateVersion>
</Target>

【讨论】:

  • @user1037993,当你重建你的项目时,有一些额外的目标(比如BeforeRebuild)。无论如何BeforeBuild 是初始任务之一,之后将执行任何构建操作。
  • 执行Rebuild 应该导致BeforeBuild 最终执行吗?无论如何,结果总是一样的。
  • 在更改输出详细程度后检查输出后,我可以确认BeforeBuild 实际上确实在其他所有事情之前被调用,我的任务也是如此。我接受了你的回答,因为它回答了我最初的问题。所以现在看来​​,出于某种原因,初始程序集版本在此过程之前被捕获并在链接文件时使用。似乎没有使用初始程序集版本的值定义任何属性。现在呢?
  • @LawrenceWard 已更新,希望对您有所帮助
【解决方案2】:

如果您希望目标在每次构建开始时运行,而不管最终目标是什么(清理、恢复、构建、发布),您可以使用InitialTargets 元素的InitialTargets 属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-06
    • 1970-01-01
    • 1970-01-01
    • 2017-02-01
    • 1970-01-01
    • 2014-02-24
    • 2013-03-29
    • 1970-01-01
    相关资源
    最近更新 更多