在设置创建过程中,我计划执行以下操作(在 C# 脚本内):
AssemblyVersion
和AssemblyFileVersion
属性值。AssemblyVersion
和 AssemblyFileVersion
属性值。现在的问题是:第2步怎么做?
我成功地完成了步骤 1,但对于步骤 2,我没有看到真正的起点。我可能要做的是使用一些本机 P/Invoke 方法,因为属性直接修改 DLL/可执行文件的版本信息资源信息。
这方面有什么提示吗?
为什么不在构建过程中读取一个DLL的
AssemblyVersion
和AssemblyFileVersion
,并将其保存回其他csproject的AssemblyInfo.cs
,然后才编译它?
事实上,我不知道是否可以直接修改DLL文件,而不需要借助一些奇特的东西。
或者,确保所有 DLL 共享一个公共的
AssemblyInfo.cs
。当您在 csproject 中添加新项目时,您可以通过添加 AssemblyInfo.cs
作为“添加为链接”来完成此操作。这样当你编译时,所有的DLL都会共享相同的AssemblyInfo.cs
,从而输出相同的AssemblyVersion
。
就我而言,我创建了一个 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")]
属性
[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建议的自动化/技巧的替代建议。
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")]
我们还可以通过编辑
.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