我正在构建一个C#应用程序,使用Git作为我的版本控制.
有没有办法在构建应用程序时自动将最后一个提交哈希嵌入可执行文件中?
例如,将提交哈希打印到控制台看起来像:
class PrintCommitHash
{
private String lastCommitHash = ?? // What do I put here?
static void Main(string[] args)
{
// Display the version number:
System.Console.WriteLine(lastCommitHash );
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这必须在构建时完成,而不是在运行时完成,因为我部署的可执行文件不会访问git repo.
可以在此处找到C++的相关问题.
编辑
Per @ mattanja的请求,我发布了我在项目中使用的git钩子脚本.设置:
由于我的linux-shelling有点生疏,脚本只是将AssemblyInfo.cs的前23行读取到临时文件,将git散列回到最后一行,然后将文件重命名为AssemblyInfo.cs.我确信有更好的方法可以做到这一点:
#!/bin/sh
cmt=$(git rev-list --max-count=1 HEAD)
head -23 AssemblyInfo.cs > AssemblyInfo.cs.tmp
echo [assembly: AssemblyFileVersion\(\"$cmt\"\)] >> AssemblyInfo.cs.tmp
mv AssemblyInfo.cs.tmp AssemblyInfo.cs
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
Joh*_*sus 68
您可以将version.txt文件嵌入到可执行文件中,然后从可执行文件中读取version.txt.要创建version.txt文件,请使用git describe --long
以下是步骤:
右键单击该项目,然后选择"属性"
在Build Events中,添加包含(注意引号)的Pre-Build事件:
"C:\ Program Files\Git\bin\git.exe"描述--long>"$(ProjectDir)\ version.txt"
这将在项目目录中创建一个version.txt文件.
这里有一些示例代码来读取嵌入的文本文件版本字符串:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
namespace TryGitDescribe
{
class Program
{
static void Main(string[] args)
{
string gitVersion= String.Empty;
using (Stream stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("TryGitDescribe." + "version.txt"))
using (StreamReader reader = new StreamReader(stream))
{
gitVersion= reader.ReadToEnd();
}
Console.WriteLine("Version: {0}", gitVersion);
Console.WriteLine("Hit any key to continue");
Console.ReadKey();
}
}
}
Run Code Online (Sandbox Code Playgroud)
Han*_*man 51
我们在git中使用标签来跟踪版本.
git tag -a v13.3.1 -m "version 13.3.1"
Run Code Online (Sandbox Code Playgroud)
您可以通过git获取带有哈希的版本:
git describe --long
Run Code Online (Sandbox Code Playgroud)
我们的构建过程将git哈希放在AssemblyInfo.cs文件的AssemblyInformationalVersion属性中:
[assembly: AssemblyInformationalVersion("13.3.1.74-g5224f3b")]
Run Code Online (Sandbox Code Playgroud)
编译后,您可以从Windows资源管理器中查看版本:
您也可以通过以下方式以编程方式获取:
var build = ((AssemblyInformationalVersionAttribute)Assembly
.GetAssembly(typeof(YOURTYPE))
.GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false)[0])
.InformationalVersion;
Run Code Online (Sandbox Code Playgroud)
其中YOURTYPE是具有AssemblyInformationalVersion属性的程序集中的任何类型.
Mar*_*lug 32
我已经创建了一个简单的nuget包,您可以将其包含在您的项目中,它将为您解决此问题:https://www.nuget.org/packages/MSBuildGitHash/
这个nuget包实现了一个"纯粹"的MSBuild解决方案.如果你不想依赖nuget包,你可以简单地将这些Targets复制到你的csproj文件中,它应该包含git hash作为自定义程序集属性:
<Target Name="GetGitHash" BeforeTargets="WriteGitHash" Condition="'$(BuildHash)' == ''">
<PropertyGroup>
<!-- temp file for the git version (lives in "obj" folder)-->
<VerFile>$(IntermediateOutputPath)gitver</VerFile>
</PropertyGroup>
<!-- write the hash to the temp file.-->
<Exec Command="git -C $(ProjectDir) describe --long --always --dirty > $(VerFile)" />
<!-- read the version into the GitVersion itemGroup-->
<ReadLinesFromFile File="$(VerFile)">
<Output TaskParameter="Lines" ItemName="GitVersion" />
</ReadLinesFromFile>
<!-- Set the BuildHash property to contain the GitVersion, if it wasn't already set.-->
<PropertyGroup>
<BuildHash>@(GitVersion)</BuildHash>
</PropertyGroup>
</Target>
<Target Name="WriteGitHash" BeforeTargets="CoreCompile">
<!-- names the obj/.../CustomAssemblyInfo.cs file -->
<PropertyGroup>
<CustomAssemblyInfoFile>$(IntermediateOutputPath)CustomAssemblyInfo.cs</CustomAssemblyInfoFile>
</PropertyGroup>
<!-- includes the CustomAssemblyInfo for compilation into your project -->
<ItemGroup>
<Compile Include="$(CustomAssemblyInfoFile)" />
</ItemGroup>
<!-- defines the AssemblyMetadata attribute that will be written -->
<ItemGroup>
<AssemblyAttributes Include="AssemblyMetadata">
<_Parameter1>GitHash</_Parameter1>
<_Parameter2>$(BuildHash)</_Parameter2>
</AssemblyAttributes>
</ItemGroup>
<!-- writes the attribute to the customAssemblyInfo file -->
<WriteCodeFragment Language="C#" OutputFile="$(CustomAssemblyInfoFile)" AssemblyAttributes="@(AssemblyAttributes)" />
</Target>
Run Code Online (Sandbox Code Playgroud)
这里有两个目标.第一个,"GetGitHash",将git哈希加载到名为BuildHash的MSBuild属性中,只有在尚未定义BuildHash的情况下才会执行此操作.如果您愿意,这允许您在命令行上将其传递给MSBuild.您可以将它传递给MSBuild,如下所示:
MSBuild.exe myproj.csproj /p:BuildHash=MYHASHVAL
第二个目标"WriteGitHash"将哈希值写入名为"CustomAssemblyInfo.cs"的临时"obj"文件夹中的文件.该文件将包含如下所示的行:
[assembly: AssemblyMetadata("GitHash", "MYHASHVAL")]
此CustomAssemblyInfo.cs文件将编译到程序集中,因此您可以使用反射来查找AssemblyMetadata
运行时.以下代码显示了当AssemblyInfo
类包含在同一程序集中时如何执行此操作.
using System.Linq;
using System.Reflection;
public static class AssemblyInfo
{
/// <summary> Gets the git hash value from the assembly
/// or null if it cannot be found. </summary>
public static string GetGitHash()
{
var asm = typeof(AssemblyInfo).Assembly;
var attrs = asm.GetCustomAttributes<AssemblyMetadataAttribute>();
return attrs.FirstOrDefault(a => a.Key == "GitHash")?.Value;
}
}
Run Code Online (Sandbox Code Playgroud)
这种设计的一些好处是它不会触及项目文件夹中的任何文件,所有变异文件都在"obj"文件夹下.您的项目也将在Visual Studio或命令行中以相同方式构建.它也可以很容易地为您的项目定制,并将与您的csproj文件一起进行源代码控制.
sch*_*ick 12
另一种方法是使用NetRevisionTool和一些On-Board Visual Studio魔术.我将在这里展示Visual Studio 2013专业版,但这也适用于其他版本.
首先下载NetRevisionTool.您在PATH中包含NetRevisionTool.exe或将其签入到您的存储库中并创建Visual Studio预构建和构建后操作并更改AssemblyInfo.cs.
将您的git-hash添加到AssemblyInformationVersion的示例如下:在您的项目设置中:
在项目的AssemblyInfo.cs中,您可以更改/添加行:
[assembly:AssemblyInformationalVersion("1.1.{dmin:2015}.{chash:6} {!} - {branch}")]
在显示的屏幕截图中,我在External/bin文件夹中的NetRevisionTool.exe中进行了检查
在构建之后,如果您然后右键单击二进制文件并转到属性,那么您应该看到类似以下内容:
希望这有助于那里的人
小智 12
我认为这个问题值得给出一个完整的循序渐进的答案.这里的策略是从预构建事件运行powershell脚本,该脚本接收模板文件并生成包含git标签+提交计数信息的AssemblyInfo.cs文件.
步骤1:根据原始AssemblyInfo.cs在Project\Properties文件夹中创建AssemblyInfo_template.cs文件,但包含:
[assembly: AssemblyVersion("$FILEVERSION$")]
[assembly: AssemblyFileVersion("$FILEVERSION$")]
[assembly: AssemblyInformationalVersion("$INFOVERSION$")]
Run Code Online (Sandbox Code Playgroud)
步骤2:创建名为InjectGitVersion.ps1的powershell脚本,其源代码为:
# InjectGitVersion.ps1
#
# Set the version in the projects AssemblyInfo.cs file
#
# Get version info from Git. example 1.2.3-45-g6789abc
$gitVersion = git describe --long --always;
# Parse Git version info into semantic pieces
$gitVersion -match '(.*)-(\d+)-[g](\w+)$';
$gitTag = $Matches[1];
$gitCount = $Matches[2];
$gitSHA1 = $Matches[3];
# Define file variables
$assemblyFile = $args[0] + "\Properties\AssemblyInfo.cs";
$templateFile = $args[0] + "\Properties\AssemblyInfo_template.cs";
# Read template file, overwrite place holders with git version info
$newAssemblyContent = Get-Content $templateFile |
%{$_ -replace '\$FILEVERSION\$', ($gitTag + "." + $gitCount) } |
%{$_ -replace '\$INFOVERSION\$', ($gitTag + "." + $gitCount + "-" + $gitSHA1) };
# Write AssemblyInfo.cs file only if there are changes
If (-not (Test-Path $assemblyFile) -or ((Compare-Object (Get-Content $assemblyFile) $newAssemblyContent))) {
echo "Injecting Git Version Info to AssemblyInfo.cs"
$newAssemblyContent > $assemblyFile;
}
Run Code Online (Sandbox Code Playgroud)
步骤3:将InjectGitVersion.ps1文件保存到BuildScripts文件夹中的解决方案目录
第4步:将以下行添加到项目的预构建事件中
powershell -ExecutionPolicy ByPass -File $(SolutionDir)\BuildScripts\InjectGitVersion.ps1 $(ProjectDir)
Run Code Online (Sandbox Code Playgroud)
第5步:构建项目.
步骤6:(可选)将AssemblyInfo.cs添加到您的git ignore文件中
这是一个在 Visual Studio 2019 中工作的简单解决方案,并将 git commit 哈希直接获取到 C# 文件中。将以下 C# 代码添加到您的解决方案中:
namespace MyNameSpace
{
[System.AttributeUsage(System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)]
sealed class GitHashAttribute : System.Attribute
{
public string Hash { get; }
public GitHashAttribute(string hsh)
{
this.Hash = hsh;
}
}
var hash = Assembly.GetEntryAssembly().GetCustomAttribute<GitHashAttribute>().Hash;
}
Run Code Online (Sandbox Code Playgroud)
如果将以下行添加到文件中,则变量hash
将包含所需的字符串.csproj
。
<Target Name="SetSourceRevisionId" BeforeTargets="InitializeSourceControlInformation">
<Exec Command="git.exe describe --long --always --dirty --exclude='*' --abbrev=40"
ConsoleToMSBuild="True" IgnoreExitCode="False">
<Output PropertyName="SourceRevisionId" TaskParameter="ConsoleOutput" />
</Exec>
</Target>
<Target Name="SetHash" AfterTargets="InitializeSourceControlInformation">
<ItemGroup>
<AssemblyAttribute Include="MyNameSpace.GitHashAttribute">
<_Parameter1>$(SourceRevisionId)</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
</Target>
Run Code Online (Sandbox Code Playgroud)
确保MyNameSpace
两个文件中的内容都符合您的需求。这里重要的一点是ItemGroup
必须将其嵌入到Target
适当的AfterTargets
集合中。
现在,使用.NET Revision Task for MSBuild并使用 Visual Studio 2019 变得非常容易。
只需安装NuGet包Unclassified.NetRevisionTaskAssemblyInfo.cs
,然后按照GitHub 文档中的说明在文件中配置所需的信息。
如果您只想要最后一次提交的哈希值(长度=8):
[assembly: AssemblyInformationalVersion("1.0-{chash:8}")]
Run Code Online (Sandbox Code Playgroud)
构建您的项目/解决方案,您将得到如下内容:
归档时间: |
|
查看次数: |
32767 次 |
最近记录: |