以编程方式更改 AssemblyVersion 和 AssemblyFileVersion 属性

问题描述 投票:0回答:3

在设置创建过程中,我计划执行以下操作(在 C# 脚本内):

  1. 读取一个DLL的
    AssemblyVersion
    AssemblyFileVersion
    属性值。
  2. 迭代项目中的所有 DLL 和可执行文件,并将这些版本应用于其
    AssemblyVersion
    AssemblyFileVersion
    属性值。

现在的问题是:第2步怎么做?

我成功地完成了步骤 1,但对于步骤 2,我没有看到真正的起点。我可能要做的是使用一些本机 P/Invoke 方法,因为属性直接修改 DLL/可执行文件的版本信息资源信息。

这方面有什么提示吗?

c# .net attributes versioninfo
3个回答
13
投票

为什么不在构建过程中读取一个DLL的

AssemblyVersion
AssemblyFileVersion
,并将其保存回其他csproject的
AssemblyInfo.cs
,然后才编译它?

事实上,我不知道是否可以直接修改DLL文件,而不需要借助一些奇特的东西。

或者,确保所有 DLL 共享一个公共的

AssemblyInfo.cs
。当您在 csproject 中添加新项目时,您可以通过添加
AssemblyInfo.cs
作为“添加为链接”来完成此操作。这样当你编译时,所有的DLL都会共享相同的
AssemblyInfo.cs
,从而输出相同的
AssemblyVersion


4
投票

就我而言,我创建了一个 T4 模板来更改 AssemblyVersion 和 AssemblyFileVersion。我将模板命名为 Assembly.tt,并将其设为链接文件(添加它时选择“添加链接”,而不是“添加”)。我的所有程序集都会拉入链接的 Assembly.tt 文件。

然后,您可以从一个位置运行 T4 模板,它将更新所有 AssemblyVersion 和 AssemblyFileVersions。您不必调用文件 AssemblyInfo.cs 即可将信息提取到 dll 中。

Assembly.tt 文件的代码是:

<#@ template language="C#" hostspecific="true" #>
// 
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
// 

using System.Reflection;

[assembly: AssemblyVersion("4.<#= this.RevisionYear #>.<#= this.RevisionNumber #>.<#= this.RevisionTime #>")]
[assembly: AssemblyFileVersion("4.<#= this.RevisionYear #>.<#= this.RevisionNumber #>.<#= this.RevisionTime #>")]
<#+
    int RevisionYear = DateTime.UtcNow.Year;
    int RevisionNumber = (int)(DateTime.UtcNow - new DateTime(DateTime.UtcNow.Year,1,1)).TotalDays;
    int RevisionTime = (int)(DateTime.UtcNow - new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, DateTime.UtcNow.Day)).TotalMinutes;
#>

上面 T4 模板的输出将是:

// 
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.
// 

using System.Reflection;

[assembly: AssemblyVersion("4.2016.284.1066")]
[assembly: AssemblyFileVersion("4.2016.284.1066")]

1
投票

属性

[AssemblyVersion()]
[AssemblyFileVersion()]
都接受常量
string
作为参数。

所以我可以在当前组件中创建一个带有

static class
const
string
,并可以将其提供给这些
attributes
作为参数,如下

    public static class App
    {
        public const string Version = "1.0.0.1";
    }

并将

AssemblyInfo.cs
更新为

[assembly: AssemblyVersion(App.Version)]
[assembly: AssemblyFileVersion(App.Version)]

这是上面@Kelly R@Gravtion建议的自动化/技巧的替代建议。


更新 1 - 使用
T4
模板

如果您想要像@KellyR建议的那样选择

T4 template
,以下可以帮助您获得该版本:


private string Version()
{
    DateTime START = new DateTime(2021,2, 14); //StartDate
    DateTime NOW = DateTime.Now;
    int numMonths = (int)(NOW.Subtract(START).Days / (365.25 / 12));
    int Major = numMonths / 12;
    int Minor = numMonths % 12;
    int Build = (int)DateTime.Now.Day;
    string Revision = $"{(int)DateTime.Now.Hour}{DateTime.Now.Minute}";
    
    return $"{Major}.{Minor}.{Build}.{Revision}";
}

START
存储项目的开始日期,用于计算到目前为止已经过去的月数。然后将
numMonths
除以 12 以获得过去的年数(将其视为
Major
版本
)并将剩余月份保留为
Minor
版本,然后将当天作为
Build
并将小时 + 分钟作为
Revision

每次构建时,您都会获得产品的最新版本。

这也可以在

T4 template
中使用,如下所示:

<#@ output extension=".cs" #>
<#@ template debug="true" language="C#" hostspecific="false" #>

using System.Reflection;

[assembly: AssemblyVersion("<#= NewVersion() #>")]
[assembly: AssemblyFileVersion("<#= NewVersion() #>")]



<#+
    private string NewVersion()
    {
        DateTime START = new DateTime(2021,2, 14); //StartDate
        DateTime NOW = DateTime.Now;
        int numMonths = (int)(NOW.Subtract(START).Days / (365.25 / 12));
        int Major = numMonths / 12;
        int Minor = numMonths % 12;
        int Build = (int)DateTime.Now.Day;
        string Revision = $"{(int)DateTime.Now.Hour}{DateTime.Now.Minute}";
    
        return $"{Major}.{Minor}.{Build}.{Revision}";

    }
    //Started On = 12-5-2021;
    
    
#>

当使用它作为

AssemblyVersion
时,请记得在
AssemblyFileVersion
中注释
AssemblyInfo.cs
T4 template

//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]

更新 2 - 使用 MsBuild

我们还可以通过编辑

.csproj
文件来更改程序集版本,添加以下内容:

  <Target Name="AssemblyVersion" BeforeTargets="CoreCompile" DependsOnTargets="PrepareForBuild">
    <PropertyGroup>
      <AssemblyInfo>Properties\AssemblyInfo.cs</AssemblyInfo>
      <AssemblyInfoContent>$([System.IO.File]::ReadAllText($(AssemblyInfo)))</AssemblyInfoContent>
      <VersionRegex>(\[\s*assembly\s*:\s*AssemblyVersion\(\s*"(\d+)\.(\d+)\.(\d+)(\.)(\d+)("\)\s*\]))</VersionRegex>
      <BuildAndRevisionRegex>(\d+\.\d+")</BuildAndRevisionRegex>
      <AssemblyVersion>$([System.Text.RegularExpressions.Regex]::Match('$(AssemblyInfoContent)', '$(VersionRegex)'))</AssemblyVersion>

      <!-- New AssemblyVersion Block -->
      <NowTime>$([System.DateTime]::Now.Year)</NowTime>
      <MajorVersion>$([MSBuild]::Subtract($(NowTime), 2023).ToString("0"))</MajorVersion>
      <MinorBuildRevision>$([System.DateTime]::Now.ToString("M.d.hhm"))</MinorBuildRevision>
      
      <AssemblyVersion>[assembly: AssemblyVersion("$(MajorVersion).$(MinorBuildRevision)")]</AssemblyVersion>
    </PropertyGroup>
    <!-- Write New AssemblyVersion Block to AssemblyInfo.cs file -->
    <WriteLinesToFile File="$(AssemblyInfo)" Lines="$([System.Text.RegularExpressions.Regex]::Replace($(AssemblyInfoContent), $(VersionRegex), $(AssemblyVersion)))" Overwrite="true" />
  </Target>

它的作用是读取

AssemblyInfo.cs
文件并使用
AssemblyVersion
regularexpressions
值替换
DateTime

查找下面的代码,我们可以将值

2023
更改为任何当前/过去的年份以生成
MajorVersion

<MajorVersion>$([MSBuild]::Subtract($(NowTime), 2023).ToString("0"))</MajorVersion>
<MinorBuildRevision>$([System.DateTime]::Now.ToString("M.d.hhm"))</MinorBuildRevision>

MajorVersion
的计算方式为
DateTime.Now.Year - 2023
,因此如果第一个发布年份是
0
,则预计它是
2023
Minor
Build
Revision
本质上是动态的,因为它是由
DateTime
组件导出的,以
"M.d.hhm"

格式给出值
DateTime.Now.ToString("M.d.hhm")

在此更新时,它给出了一个值

8.23.0458
,而随着主要版本的出现,它变成了
0.8.23.0458

© www.soinside.com 2019 - 2024. All rights reserved.