MSBuild:确保在任何其他构建步骤之前运行目标

Law*_*ard 10 c# msbuild

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

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

<Import Project="$(ProjectDir)Properties\PublishVersion.proj" />
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

现在它确实在构建完成之前执行,但绝对不会在它启动之前执行,因为当我查看生成的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>
Run Code Online (Sandbox Code Playgroud)

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

对PublishVersion.proj进行更改有时似乎没有生效,我需要清理解决方案并在影响之前重新启动visual studio.

Meh*_*hin 8

也许你必须使用BeforeBuild目标.

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

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

对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;
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

上述任务生成一个包含AssemblyVersion元数据或所需内容的文件.

最后,您必须更改项目文件,如下所示:

<UsingTask TaskName="Foo.Build.Tasks.GenerateVersion" AssemblyFile="Foo.Build.Tasks.dll" />
Run Code Online (Sandbox Code Playgroud)
<Target Name="BeforeBuild">
  <GenerateVersion>
    <Output TaskParameter="GeneratedFiles" ItemName="Compile" />
  </GenerateVersion>
</Target>
Run Code Online (Sandbox Code Playgroud)


The*_*ide 5

如果您希望目标在每次构建开始时运行,无论最终目标被称为什么(清理、恢复、构建、发布),您可以使用该元素InitialTargets的属性Project