Visual Studio 2017中的自动版本控制(.NET Core)

Jas*_*n H 93 c# visual-studio .net-core visual-studio-2017 .net-standard

我花了几个小时的时间试图找到一种在.NETCoreApp 1.1(Visual Studio 2017)中自动增加版本的方法.

我知道AssemblyInfo.cs是在文件夹中动态创建的: obj/Debug/netcoreapp1.1/

它不接受旧的方法: [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.*")]

如果我将项目设置为包我可以在那里设置版本,但这似乎用于构建AssemblyInfo.cs文件.

我的问题是,有没有人想出如何控制.NET Core(或.NETStandard)项目中的版本.

MiF*_*vil 58

<Deterministic>False</Deterministic><PropertyGroup>.csproj 的一部分中添加 

MakeVersion*工作的解决方法在".Net Core#22660上的[AssemblyVersion]中为通配符混淆错误消息"中描述

只有在构建不确定时才允许使用通配符,这是.Net Core项目的默认设置.添加  <Deterministic>False</Deterministic> 到csproj修复了这个问题.

.Net核心开发人员认为在http://blog.paranoidcoding.com/2016/04/05/deterministic-builds-in-roslyn.html编译器中描述的确定性构建有益的原因应该是确定性的:相同的输入生成相同的输出# 372

但是,如果您使用的是TeamCity,TFS或其他CI/CD工具,最好保持版本号受控制并增加它们并将其作为参数传递给构建(如其他答案中所建议的那样),例如

msbuild /t:build /p:Version=YourVersionNumber /p:AssemblyVersion=YourVersionNumber
Run Code Online (Sandbox Code Playgroud)

NuGet包的包装编号

msbuild /t:pack /p:Version=YourVersionNumber   
Run Code Online (Sandbox Code Playgroud)


joe*_*and 55

如果您使用Visual Studio Team Services/TFS或其他一些CI构建过程来内置版本控制,则可以使用msbuild的Condition属性,例如:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">0.0.1-local</Version>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(BUILD_BUILDNUMBER)</Version>
    <TargetFramework>netcoreapp1.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="1.1.2" />
  </ItemGroup>

</Project>
Run Code Online (Sandbox Code Playgroud)

这将告诉.NET Core编译器使用BUILD_BUILDNUMBER环境变量中的任何内容(如果它存在),或者0.0.1-local如果您在本地计算机上进行构建则回退到.


rav*_*oll 21

我一直在使用csproj配置格式为VS2017中的Net Core应用程序寻找版本增量器.

我找到了一个名为dotnet bump的项目,该项目适用于project.json格式,但很难找到.csproj格式的解决方案.作者dotnet bump实际上提出了.csproj格式的解决方案,它被称为MSBump.

在GitHub上有一个项目:

https://github.com/BalassaMarton/MSBump

在那里你可以看到Nuget上的代码及其可用的代码.只需在Nuget上搜索MSBump.

  • 是的,它还支持多目标项目。 (2认同)
  • 考虑使用GitVersioning.它可能适合在CI环境中运行.https://github.com/AArnott/Nerdbank.GitVersioning (2认同)
  • 即使您没有更改任何内容,MSBump 也会在每次构建时增加版本,从长远来看,这会导致很多问题。有时版本不同步,一个版本落后于另一个。 (2认同)

Hol*_*Jan 13

我提出的解决方案与旧的AssemblyVersion属性几乎相同,只有星号(*) - AssemblyVersion("1.0. ")*

对价值观的AssemblyVersion的AssemblyFileVersion是MSBuild项目.csproj的文件(而不是在AssemblyInfo.cs中)财产文件版本(生成AssemblyFileVersionAttribute)和的AssemblyVersion(产生AssemblyVersionAttribute).在MSBuild过程中,我们使用自定义MSBuild任务生成版本号,然后使用来自task的新值覆盖这些FileVersionAssemblyVersion属性的值.

首先,我们创建自定义MSBuild任务GetCurrentBuildVersion:

public class GetCurrentBuildVersion : Task
{
    [Output]
    public string Version { get; set; }
 
    public string BaseVersion { get; set; }
 
    public override bool Execute()
    {
        var originalVersion = System.Version.Parse(this.BaseVersion ?? "1.0.0");
 
        this.Version = GetCurrentBuildVersionString(originalVersion);
 
        return true;
    }
 
    private static string GetCurrentBuildVersionString(Version baseVersion)
    {
        DateTime d = DateTime.Now;
        return new Version(baseVersion.Major, baseVersion.Minor,
            (DateTime.Today - new DateTime(2000, 1, 1)).Days,
            ((int)new TimeSpan(d.Hour, d.Minute, d.Second).TotalSeconds) / 2).ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

任务类继承自Microsoft.Build.Utilities.Core NuGet包中的Microsoft.Build.Utilities.Task类.它在输入上使用BaseVersion属性(可选)并在Version输出属性中返回生成的版本.获取版本号的逻辑与.NET自动版本控制相同(内部版本号是自2000年1月1日起的天数,而修订版是午夜后的半秒).

要构建此MSBuild任务,我们将.NET Class 1.3类库项目类型与此类一起使用.

.csproj文件可能如下所示:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard1.3</TargetFramework>
    <AssemblyName>DC.Build.Tasks</AssemblyName>
    <RootNamespace>DC.Build.Tasks</RootNamespace>
    <PackageId>DC.Build.Tasks</PackageId>
    <AssemblyTitle>DC.Build.Tasks</AssemblyTitle>
  </PropertyGroup>
 
  <ItemGroup>
    <PackageReference Include="Microsoft.Build.Framework" Version="15.1.1012" />
    <PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.1.1012" />
  </ItemGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)

这个任务项目也可以在我的GitHub holajan/DC.Build.Tasks中找到

现在我们设置MSBuild来使用此任务并设置FileVersionAssemblyVersion属性.在.csproj文件中,它看起来像这样:

<Project Sdk="Microsoft.NET.Sdk">
  <UsingTask TaskName="GetCurrentBuildVersion" AssemblyFile="$(MSBuildThisFileFullPath)\..\..\DC.Build.Tasks.dll" />
 
  <PropertyGroup>
    ...
    <AssemblyVersion>1.0.0.0</AssemblyVersion>
    <FileVersion>1.0.0.0</FileVersion>
  </PropertyGroup>
 
  ...
 
  <Target Name="BeforeBuildActionsProject1" BeforeTargets="BeforeBuild">
    <GetCurrentBuildVersion BaseVersion="$(FileVersion)">
      <Output TaskParameter="Version" PropertyName="FileVersion" />
    </GetCurrentBuildVersion>
    <PropertyGroup>
      <AssemblyVersion>$(FileVersion)</AssemblyVersion>
    </PropertyGroup>
  </Target>
 
</Project>
Run Code Online (Sandbox Code Playgroud)

这里的进口商品:

  • 提到UsingTaskDC.Build.Tasks.dll导入GetCurrentBuildVersion任务.它假定此dll文件位于.csproj文件的父目录中.
  • 我们的BeforeBuildActionsProject1调用任务的目标必须具有每个项目的唯一名称,以防我们在解决方案中有更多项目调用GetCurrentBuildVersion任务.

此解决方案的优点是它不仅可以从构建服务器上构建,还可以在dotnet构建或Visual Studio的手动构建中工作.

  • 我建议在方法“GetCurrentBuildVersionString()”中使用“DateTime.UtcNow”而不是“DateTime.Now”,特别是如果代码是在自动构建机器上执行的。当您的计算机切换到/从夏令时时,它们可能会在凌晨 2 点或凌晨 3 点运行。在这种情况下使用`DateTime.Now`,你可能会在版本方面倒退。诚然,这是一个极端情况,我也承认我很挑剔。:-) 此外,如果您在所有构建机器上配置相同的时区并且不适应夏令时,问题也会消失。 (4认同)

Fab*_*doy 11

您可以使用MSBuild属性函数根据当前日期设置版本后缀:

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
  <VersionSuffix>pre$([System.DateTime]::UtcNow.ToString(yyyyMMdd-HHmm))</VersionSuffix>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

这将输出一个名为PackageName.1.0.0-pre20180807-1711.nupkg的包.

有关MSBuild属性函数的更多详细信息:https://docs.microsoft.com/en-us/visualstudio/msbuild/property-functions


Gig*_*igi 9

现在,这些值在.csproj文件中设置:

<PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
    <AssemblyVersion>1.0.6.0</AssemblyVersion>
    <FileVersion>1.0.6.0</FileVersion>
    <Version>1.0.1</Version>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

如果您进入项目设置的" 包"选项卡,则这些值与您看到的值相同.虽然我认为您不能使用*自动增量版本,但您可以做的是引入一个后处理步骤来替换您的版本(例如,作为持续集成的一部分).

  • 我担心这会是答案.我将看看我是否可以进行预构建步骤来增加它. (6认同)
  • 他们为什么删除自动增量?多年来,它对我来说非常好,非常简单.我推动master,CI构建和增量,然后使用一些PS脚本直接从构建的DLL读取版本,然后在推送到NuGet时使用该版本作为arg.很简单.现在坏了. (5认同)
  • 正如在另一个线程中指出的那样,新的csproj格式允许您关闭assemblyinfo文件的自动生成并指定您自己的文件.我遵循了natemcmaster的回答,并使用了标准的AssemblyInfo.cs文件:/sf/ask/2949689291/ (3认同)

Chr*_*zie 9

dotnet build /p:AssemblyVersion=1.2.3.4

我回答说:"有没有人想出如何控制.NET Core(或.NETStandard)项目中的版本." 我发现这个问题试图在CI构建的上下文中解决这个问题.我想将程序集版本设置为CI内部版本号.

  • 我回答说:"有没有人想出如何控制.NET Core(或.NETStandard)项目中的版本." 我发现这个问题试图在CI构建的上下文中解决这个问题.我想将程序集版本设置为CI内部版本号.如果您认为这与手头的问题无关,我很抱歉. (4认同)
  • 标题为“Visual Studio 2017 (.NET Core) 中的自动版本控制”。手动构建它到底在哪里符合“Visual Studio 2017”? (2认同)

Cla*_*e76 8

您可以在 csproj 文件中执行如下操作。我没搞清楚数学。我在 Stack Overflow 上的其他地方发现了它,但这可以工作,并且会为您提供类似于 1.0.* 的版本。

<PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <FileVersion>1.0.$([System.DateTime]::UtcNow.Date.Subtract($([System.DateTime]::Parse("2000-01-01"))).TotalDays).$([System.Math]::Floor($([MSBuild]::Divide($([System.DateTime]::UtcNow.TimeOfDay.TotalSeconds), 1.32))))</FileVersion>
    <Version>1.0.$([System.DateTime]::UtcNow.Date.Subtract($([System.DateTime]::Parse("2000-01-01"))).TotalDays)</Version>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)


Kir*_*san 8

综上所述:您可以AssemblyInfo.cs通过以下方式恢复旧行为:

<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Deterministic>false</Deterministic>
Run Code Online (Sandbox Code Playgroud)

但不建议使用这种方法,因为关闭GenerateAssemblyInfo可能会导致基础设施问题,例如。更具选择性的方法:

<Deterministic>false</Deterministic>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute>
<AssemblyVersion>1.2.*</AssemblyVersion>
Run Code Online (Sandbox Code Playgroud)

你不需要AssemblyInfo.cs更多了。


Jas*_*n H 6

我接受了上面的答案,因为@Gigi是正确的(截至目前),但我很恼火,并提出了以下PowerShell脚本.

首先,我在我的解决方案文件夹(UpdateBuildVersion.ps1)中有脚本:

#Get Path to csproj
$path = "$PSScriptRoot\src\ProjectFolder\ProjectName.csproj"

#Read csproj (XML)
$xml = [xml](Get-Content $path)

#Retrieve Version Nodes
$assemblyVersion = $xml.Project.PropertyGroup.AssemblyVersion
$fileVersion = $xml.Project.PropertyGroup.FileVersion

#Split the Version Numbers
$avMajor, $avMinor, $avBuild  = $assemblyVersion.Split(".")
$fvMajor, $fvMinor, $fvBuild = $fileVersion.Split(".")

#Increment Revision
$avBuild = [Convert]::ToInt32($avBuild,10)+1
$fvBuild = [Convert]::ToInt32($fvBuild,10)+1

#Put new version back into csproj (XML)
$xml.Project.PropertyGroup.AssemblyVersion = "$avMajor.$avMinor.$avBuild"
$xml.Project.PropertyGroup.FileVersion = "$fvMajor.$fvMinor.$fvBuild"

#Save csproj (XML)
$xml.Save($path)
Run Code Online (Sandbox Code Playgroud)

我把它添加到csproj文件中:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <AssemblyVersion>0.0.1</AssemblyVersion>
    <FileVersion>0.0.1</FileVersion>
    <PreBuildEvent>powershell.exe –NonInteractive –ExecutionPolicy Unrestricted -command "& {$(SolutionDir)UpdateBuildVersion.ps1}"</PreBuildEvent>
  </PropertyGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)

即使将其设置为PreBuildEvent,事实上版本号在文件加载到内存之后才会更新,因此版本号在下一次构建之前不会反映出来.实际上,您可以将其更改为PostBuildEvent,它将具有相同的效果.

我还创建了以下两个脚本:(UpdateMinorVersion.ps1)

#Get Path to csproj
$path = "$PSScriptRoot\src\ProjectFolder\ProjectName.csproj"

#Read csproj (XML)
$xml = [xml](Get-Content $path)

#Retrieve Version Nodes
$assemblyVersion = $xml.Project.PropertyGroup.AssemblyVersion
$fileVersion = $xml.Project.PropertyGroup.FileVersion

#Split the Version Numbers
$avMajor, $avMinor, $avBuild  = $assemblyVersion.Split(".")
$fvMajor, $fvMinor, $fvBuild = $fileVersion.Split(".")

#Increment Minor Version - Will reset all sub nodes
$avMinor = [Convert]::ToInt32($avMinor,10)+1
$fvMinor = [Convert]::ToInt32($fvMinor,10)+1
$avBuild = 0
$fvBuild = 0

#Put new version back into csproj (XML)
$xml.Project.PropertyGroup.AssemblyVersion = "$avMajor.$avMinor.$avBuild"
$xml.Project.PropertyGroup.FileVersion = "$fvMajor.$fvMinor.$fvBuild"

#Save csproj (XML)
$xml.Save($path)
Run Code Online (Sandbox Code Playgroud)

(UpdateMajorVersion.ps1)

#Get Path to csproj
$path = "$PSScriptRoot\src\ProjectFolder\ProjectName.csproj"

#Read csproj (XML)
$xml = [xml](Get-Content $path)

#Retrieve Version Nodes
$assemblyVersion = $xml.Project.PropertyGroup.AssemblyVersion
$fileVersion = $xml.Project.PropertyGroup.FileVersion

#Split the Version Numbers
$avMajor, $avMinor, $avBuild  = $assemblyVersion.Split(".")
$fvMajor, $fvMinor, $fvBuild = $fileVersion.Split(".")

#Increment Major Version - Will reset all sub nodes
$avMajor = [Convert]::ToInt32($avMajor,10)+1
$fvMajor = [Convert]::ToInt32($fvMajor,10)+1
$avMinor = 0
$fvMinor = 0
$avBuild = 0
$fvBuild = 0

#Put new version back into csproj (XML)
$xml.Project.PropertyGroup.AssemblyVersion = "$avMajor.$avMinor.$avBuild"
$xml.Project.PropertyGroup.FileVersion = "$fvMajor.$fvMinor.$fvBuild"

#Save csproj (XML)
$xml.Save($path)
Run Code Online (Sandbox Code Playgroud)


Tag*_*agc 6

我在这里设置了一个简单的CLI工具来设置.csproj .NET Core版本字符串.您可以将它与GitVersion等工具结合使用,以便在CI构建期间实现自动版本冲突,如果这就是您所追求的.


Stu*_*per 6

感谢@joelsand 为我指明了正确的方向。

当 DevOps Build 运行时,我不得不稍微改变他的答案,我得到以下异常

指定的版本字符串不符合推荐格式-major.minor.build.revision

我不得不在major.minor.build 部分的末尾添加$(BUILD_BUILDNUMBER)。为了对实际版本进行重复数据删除,我还使用了版本前缀:

<PropertyGroup>
    <VersionPrefix>1.0.3</VersionPrefix>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">$(VersionPrefix)-local</Version>
    <Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(VersionPrefix)-$(BUILD_BUILDNUMBER)</Version>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)


Ant*_*uez 6

对我有用的是使用 定义 Patch 和 Revision PropertyGroup,然后您可以使用此变量作为版本(如果需要,还可以使用前缀)。版本号必须是短数字,因此我使用 YearMonth 表示补丁,使用 MinutesOfDay 表示修订。将此行添加到您的 csproj 文件中:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <PropertyGroup>
        <VersionMajor>0</VersionMajor>
        <VersionMinor>9</VersionMinor>
        <VersionPatch Condition="'$(VersionPatch)' == ''">$([System.DateTime]::UtcNow.ToString("yyMM"))</VersionPatch>
        <VersionRevision Condition="'$(VersionRevision)' == ''">$([System.DateTime]::UtcNow.TimeOfDay.TotalMinutes.ToString("0"))</VersionRevision>
    </PropertyGroup>

    <PropertyGroup>
        <OutputType>...</OutputType>
        <TargetFramework>net5.0</TargetFramework>
        <Title>Software Title</Title>
        <Description>...</Description>
        <Authors>...</Authors>
        <Version>$(VersionMajor).$(VersionMinor).$(VersionPatch).$(VersionRevision)</Version>
    </PropertyGroup>

    ....

</Project>
Run Code Online (Sandbox Code Playgroud)

它可以利用文件以通用方式实现Directory.build.props。更多信息请参见:https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-your-build? view=vs-2019

只需在项目文件夹中添加一个具有此名称的文件并将这些行放在那里即可。


我在这里寻找共享项目的解决方案。就我而言,我解决了这个问题,Version.build.props在我的共享项目中添加了一个具有上面所示结构的文件,并且在使用我的共享代码的项目的任何 csproj 文件中只添加了一个新行:

<!-- Shared project import -->
<Import Project="..\Shared\Shared.projitems" Label="Shared" /> 
<!-- Version number generator -->
<Import Project="$([MSBuild]::GetPathOfFileAbove('Version.Build.props', '$(MSBuildThisFileDirectory)../Shared/'))" />
Run Code Online (Sandbox Code Playgroud)

我会将这段代码留在这里,以防万一有人需要它。

*解决方案针对 .Net5 进行了测试,但应该适用于早期版本。


Tue*_*ved 5

使用 GIT 的标签/描述功能,根据您的 GIT 设置启用 .NET Core / .NET 无论项目的版本控制。

我一直在使用 Prebuild.targets.xml 文件,该文件位于项目的根文件夹中,并包含在 csproj 文件中,如下所示:

<Project Sdk="Microsoft.NET.Sdk">
  <Import Project="PreBuild.targets.xml" />
  ...
  <PropertyGroup>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
Run Code Online (Sandbox Code Playgroud)

使用“GenerateAssembyInfo”标签禁用自动程序集信息生成。

然后 Prebuild.targets.xml 将生成一个 CommonAssemblyInfo.cs 文件,您可以在其中根据您的 GIT 版本包含所需的版本标签

注意:我在其他地方找到了 Prebuilds.targets.xml,所以没有费心清理它。)

Prebuild.targets.xml 文件:

    <?xml version="1.0" encoding="utf-8" ?>
    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
     
      <UsingTask
        TaskName="GetVersion"
        TaskFactory="CodeTaskFactory"
        AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
        <ParameterGroup>
          <VersionString ParameterType="System.String" Required="true" />
          <Version ParameterType="System.String" Output="true" />
          <Commit ParameterType="System.String" Output="true" />
          <VersionSuffix ParameterType="System.String" Output="true" />
        </ParameterGroup>
        <Task>
          <!--<Reference Include="" />-->
          <Using Namespace="System"/>
          <Using Namespace="System.IO"/>
          <Using Namespace="System.Text.RegularExpressions" />
          <Code Type="Fragment" Language="cs">
            <![CDATA[
              var match = Regex.Match(VersionString, @"^(?<major>\d+)\.(?<minor>\d+)(\.?(?<patch>\d+))?-(?<revision>\d+)-(?<commit>[a-z0-9-]+)$");
              int major, minor, patch, revision;
              Int32.TryParse(match.Groups["major"].Value, out major);
              Int32.TryParse(match.Groups["minor"].Value, out minor);
              Int32.TryParse(match.Groups["patch"].Value, out patch);
              Int32.TryParse(match.Groups["revision"].Value, out revision);
              _Version = new Version(major, minor, patch, revision).ToString();
              _Commit = match.Groups["commit"].Value;
            ]]>
          </Code>
        </Task>
      </UsingTask>
     
      <UsingTask
        TaskName="GitExistsInPath"
        TaskFactory="CodeTaskFactory"
        AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
        <ParameterGroup>
          <Exists ParameterType="System.Boolean" Output="true" />
        </ParameterGroup>
        <Task>
          <!--<Reference Include="" />-->
          <Using Namespace="System"/>
          <Using Namespace="System.IO"/>
          <Using Namespace="System.Text.RegularExpressions" />
          <Code Type="Fragment" Language="cs">
            <![CDATA[
            var values = Environment.GetEnvironmentVariable("PATH");
            foreach (var path in values.Split(';')) {
                var exeFullPath = Path.Combine(path, "git.exe");
                if (File.Exists(exeFullPath)) {
                    Exists = true;
                    return true;
                }
                var cmdFullPath = Path.Combine(path, "git.cmd");
                if (File.Exists(cmdFullPath)) {
                    Exists = true;
                    return true;
            }
            }
            Exists = false;
            ]]>
          </Code>
        </Task>
      </UsingTask>
     
      <Target Name="CreateCommonVersionInfo" BeforeTargets="CoreCompile">
        <Message Importance="high" Text="CreateCommonVersionInfo" />
     
        <GitExistsInPath>
          <Output TaskParameter="Exists" PropertyName="GitExists"/>
        </GitExistsInPath>
        <Message Importance="High" Text="git not found!" Condition="!$(GitExists)"/>
          
        <Exec Command="git describe --tags --long --dirty > $(ProjectDir)version.txt" Outputs="$(ProjectDir)version.txt" WorkingDirectory="$(SolutionDir)" IgnoreExitCode="true" Condition="$(GitExists)">
          <Output TaskParameter="ExitCode" PropertyName="ExitCode" />
        </Exec>
        <Message Importance="high" Text="Calling git failed with exit code $(ExitCode)" Condition="$(GitExists) And '$(ExitCode)'!='0'" />
        
        <ReadLinesFromFile File="$(ProjectDir)version.txt" Condition="$(GitExists) And '$(ExitCode)'=='0'">
          <Output TaskParameter="Lines" ItemName="OutputLines"/>
        </ReadLinesFromFile>
        <Message Importance="High" Text="Tags: @(OutputLines)" Condition="$(GitExists) And '$(ExitCode)'=='0'"/>

        <Delete Condition="Exists('$(ProjectDir)version.txt')" Files="$(ProjectDir)version.txt"/>
     
        <GetVersion VersionString="@(OutputLines)" Condition="$(GitExists) And '$(ExitCode)'=='0'">
          <Output TaskParameter="Version" PropertyName="VersionString"/>
          <Output TaskParameter="Commit" PropertyName="Commit"/>
        </GetVersion>
          
        <PropertyGroup>
          <VersionString Condition="'$(VersionString)'==''">0.0.0.0</VersionString>
        </PropertyGroup>
     
        <Message Importance="High" Text="Creating CommonVersionInfo.cs with version $(VersionString) $(Commit)" />
     
        <WriteLinesToFile Overwrite="true" File="$(ProjectDir)CommonAssemblyInfo.cs" Encoding="UTF-8" Lines='using System.Reflection%3B
     
    // full version: $(VersionString)-$(Commit)
     
    [assembly: AssemblyVersion("$(VersionString)")]
    [assembly: AssemblyInformationalVersion("$(VersionString)")] 
    [assembly: AssemblyFileVersion("$(VersionString)")]' />
        
      </Target>
    </Project>
Run Code Online (Sandbox Code Playgroud)

编辑:如果您正在使用 MSBUILD 进行构建

 $(SolutionDir)
Run Code Online (Sandbox Code Playgroud)

可能会给您带来麻烦,请使用

 $(ProjectDir)
Run Code Online (Sandbox Code Playgroud)

反而


Chr*_*pin 5

  <PropertyGroup>
    <SecondsSinceEpoch>$([System.DateTime]::UtcNow.Subtract($([System.DateTime]::MinValue)).TotalSeconds)</SecondsSinceEpoch>
    <Revision>$([System.Math]::Truncate($([System.Decimal]::Remainder($(SecondsSinceEpoch), 100000))))</Revision>
    <Version>1.7.0.$(Revision)</Version>
    <AssemblyVersion>$(Version)</AssemblyVersion>
    <FileVersion>$(Version)</FileVersion>
  </PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

我对通过设置一个体面的价值的看法.csproj。不幸的是,如果您的下一次重建是在几100000秒钟之后,那么它将是相同的值。不过,比MSBump更好的是让每次构建重新构建

如果构建缓慢或自动化,可以使用TotalMinutesTotalDays等。