扩展 RobinDotNet 的解决方案:
Protip:您可以在每次构建时从 .csproj 文件 MSBuild 配置中自动运行程序或脚本来为您执行此操作。我为我当前维护的一个 Web 应用程序执行此操作,执行 Cygwin bash shell 脚本来执行一些版本控制 h4x 以从 Git 历史计算版本号,然后预处理编译到构建输出中的程序集信息源文件。
可以做类似的事情来解析项目文件中的 ClickOnce 版本号,即 Project.PropertyGroup.ApplicationRevision 和 Project.PropertyGroup.ApplicationVersion(虽然我不知道版本字符串的含义,但你可以猜测直到它中断然后修复它)并将该版本信息插入到程序集信息中。
我不知道 ClickOnce 版本何时更新,但可能是在构建过程之后,因此您可能需要修改此解决方案以获取编译的新数字。 我猜总是有/*h4x*/ +1。
我使用 Cygwin 是因为 *nix 脚本编写比 Windows 好得多,而且解释代码为您省去了 在构建之前构建预构建程序的麻烦,但是您可以使用任何您想要的技术来编写程序想要(包括 C#/.NET)。预处理器的命令行进入PreBuildEvent:
<PropertyGroup>
<PreBuildEvent>
$(CYGWIN_ROOT)bin\bash.exe --login -c refresh-version
</PreBuildEvent>
</PropertyGroup>
正如您想象的那样,这发生在构建阶段之前,因此您可以在编译之前有效地预处理您的源代码。我不想自动编辑Properties\AssemblyInfo.cs 文件,所以为了安全起见,我所做的是创建一个Properties\VersionInfo.base.cs 文件,其中包含带有版本信息的类的文本模板,并在项目中标记为BuildAction=None设置,使其不与项目一起编译:
using System.Reflection;
using EngiCan.Common.Properties;
[assembly: AssemblyVersion("0.$REVNUM_DIV(100)$.$REVNUM_MOD(100)$.$DIRTY$")]
[assembly: AssemblyRevisionIdentifier("$REVID$")]
(为了简单/复杂,使用了一种非常肮脏、穷人的占位符语法,类似于 Windows 的环境变量,并添加了一些额外的 h4x)
AssemblyRevisionIdentifierAttribute 是我创建的用于保存 Git SHA1 的自定义属性,因为它对开发人员来说比 a.b.c.d 更有意义。
我的refresh-version 程序然后将该文件复制到Properties\VersionInfo.cs,然后替换它已经计算/解析的版本信息(我使用sed(1) 进行替换,这是使用Cygwin 的另一个好处)。 Properties\VersionInfo.cs 已编译到程序中。该文件一开始可能是空的,您应该通过版本控制系统忽略它,因为它会自动更改,并且生成它的信息已经存储在其他地方。