programing

에 깃 커밋 해시를 포함합니다.NET dll

yellowcard 2023. 9. 7. 21:38
반응형

에 깃 커밋 해시를 포함합니다.NET dll

저는 Git을 버전 컨트롤로 사용하여 C# 어플리케이션을 만들고 있습니다.

애플리케이션을 구축할 때 실행 파일에 마지막 커밋 해시를 자동으로 내장하는 방법이 있습니까?

예를 들어 콘솔에 커밋 해시를 인쇄하면 다음과 같습니다.

class PrintCommitHash
{
    private String lastCommitHash = ?? // What do I put here?
    static void Main(string[] args)
    {
        // Display the version number:
        System.Console.WriteLine(lastCommitHash );
    }
}

이 작업은 런타임이 아니라 빌드 에 수행해야 합니다. 배포된 실행 파일에서는 gitrepo에 액세스할 수 없기 때문입니다.

C++와 관련된 질문은 여기에서 확인할 수 있습니다.



@mattanja님의 요청에 따라 프로젝트에서 사용하는 git hook 스크립트를 올립니다.설정:

  • 후크는 path_to_project\.git\hooks 아래에 있는 리눅스 셸 스크립트입니다.
  • msysgit를 사용하는 경우 후크 폴더에 이미 샘플 스크립트가 일부 포함되어 있습니다.git를 호출하려면 스크립트 이름에서 '.sample' 확장자를 제거합니다.
  • 후크 스크립트의 이름은 후크 스크립트를 호출하는 이벤트와 일치합니다.저 같은 경우에는 사후 커밋과 사후 합병을 수정했습니다.
  • AssemblyInfo.cs 파일은 프로젝트 경로 바로 아래에 있습니다(.git 폴더와 동일한 수준).23개의 라인을 포함하고 있으며, 24번째를 생성하기 위해 깃을 사용합니다.

제 리눅스 셸링이 약간 녹슬었기 때문에 스크립트는 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

업데이트:

제가 처음에 이 질문에 대답을 한 이후로 상황이 발전했습니다.Microsoft.NET.Sdk( project를 을 의미함) 조건이 를 추가할 수 포함되었습니다 (sdk 스타일 프로젝트를 사용해야 함을 의미함) 다음 조건이 충족되는 경우 nuget 패키지 메타데이터에 커밋 해시를 추가할 수 있습니다.

  1. <SourceRevisionId>속성을 정의해야 합니다.은 다음과할 수 :은과은을여다수할이다수ess:이ta할g은ny
<Target Name="SetSourceRevisionId" BeforeTargets="InitializeSourceControlInformation">
    <Exec 
      Command="git describe --long --always --dirty --exclude=* --abbrev=8"
      ConsoleToMSBuild="True"
      IgnoreExitCode="False"
      >
      <Output PropertyName="SourceRevisionId" TaskParameter="ConsoleOutput"/>
    </Exec>
  </Target>

은 을 할 을 합니다 은 합니다 을 을 설정하는 명령을 실행합니다.SourceRevisionId해시(8자)의 축약이 됩니다.BeforeTargets(BeforeTargets)를 사용하면 어셈블리 정보 버전이 생성되기 전에 이 작업이 실행됩니다.

  1. 메타데이터에 nuget 에 를 시키기 시키기,<RepositoryUrl>또한 정의해야 합니다.

  2. <SourceControlInformationFeatureSupported>속성은 다음과 같습니다.true nuget pack 이 SourceRevisionId.를.

저는 이 새로운 기술이 더 깨끗하고 일관적이기 때문에 사람들이 MSBuildGitHash 패키지를 사용하지 않도록 할 것입니다.

원본:

프로젝트에 포함시킬 수 있는 간단한 nuget 패키지를 만들었습니다. https://www.nuget.org/packages/MSBuildGitHash/

이 nuget 패키지는 "순수한" MSBuild 솔루션을 구현합니다.nuget 패키지에 의존하지 않는 것이 좋다면 csproj 파일에 이러한 Targets를 복사할 수 있으며 사용자 지정 어셈블리 속성으로 git 해시를 포함해야 합니다.

<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 &gt; $(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>

여기 목표물이 두 개 있습니다.첫 번째 "GetGitHash"는 GitHash를 BuildHash라는 MSBuild 속성에 로드합니다. 이것은 BuildHash가 아직 정의되지 않은 경우에만 수행됩니다.원하는 경우 명령줄의 MSBuild로 전달할 수 있습니다.다음과 같이 MSBuild에 전달할 수 있습니다.

MSBuild.exe myproj.csproj /p:BuildHash=MYHASHVAL

두 번째 대상인 "WriteGitHash"는 "CustomAssemblyInfo.cs "이라는 임시 "obj" 폴더에 있는 파일에 해시 값을 쓸 것입니다.이 파일에는 다음과 같은 행이 포함됩니다.

[assembly: AssemblyMetadata("GitHash", "MYHASHVAL")]

하여 은 reflection 하여 할 되므로 에 할 하여 AssemblyMetadata는 ⑥ 다음 보여줍니다 있는지실행코드어떻게 이것해질녘 the 보여줍니다 있는지 this can be how shows when done 해질녘 the 다음 code following 코드이것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;
    }
}

이 디자인의 장점은 프로젝트 폴더의 어떤 파일도 건드리지 않고 모든 변형된 파일이 "obj" 폴더 아래에 있다는 것입니다.또한 프로젝트는 Visual Studio 내에서 또는 명령줄에서 동일하게 구축됩니다.또한 프로젝트에 맞게 쉽게 커스터마이징할 수 있으며 csproj 파일과 함께 소스 제어가 가능합니다.

버전을 내장할 수 있습니다.txt 파일을 실행 파일에 넣은 다음 버전을 읽습니다.실행 파일에서 txt를 내보냅니다.버전을 만들기 위해서.txt 파일, 사용git describe --long

단계는 다음과 같습니다.

빌드 이벤트를 사용하여 깃 호출

  • 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 Properties(속성)를 선택합니다.

  • Build Events(빌드 이벤트)에서 다음을 포함하는 Pre-Build 이벤트를 추가합니다(따옴표 참고).

    "C:\Program Files\Git\bin\git.exe"는 --long > "$(ProjectDir)\version을 설명합니다.txt"

    그러면 버전이 생성됩니다.프로젝트 디렉토리에 있는 txt 파일.

버전을 포함합니다.실행 파일의 txt

  • 프로젝트를 마우스 오른쪽 단추로 클릭하고 기존 항목 추가를 선택합니다.
  • 버전을 추가합니다.txt 파일(모든 파일을 볼 수 있도록 파일 선택 필터 변경)
  • After version.txt가 추가되고 Solution Explorer에서 마우스 오른쪽 버튼을 클릭하고 Properties(속성)를 선택합니다.
  • 빌드 작업을 내장된 리소스로 변경
  • 복사를 항상 복사하도록 출력 디렉토리로 변경
  • 버전 추가..gitignore 파일에 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();
        }
    }
}

우리는 버전을 추적하기 위해 태그를 사용합니다.

git tag -a v13.3.1 -m "version 13.3.1"

git에서 해시로 버전을 얻을 수 있는 방법은 다음과 같습니다.

git describe --long

우리의 빌드 프로세스는 git 해시를 AssemblyInfo.cs 파일의 AssemblyInformationVersion 특성에 넣습니다.

[assembly: AssemblyInformationalVersion("13.3.1.74-g5224f3b")]

컴파일이 끝나면 Windows 탐색기에서 버전을 볼 수 있습니다.

enter image description here

다음을 통해 프로그래밍 방식으로 얻을 수도 있습니다.

var build = ((AssemblyInformationalVersionAttribute)Assembly
  .GetAssembly(typeof(YOURTYPE))
  .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false)[0])
  .InformationalVersion;

여기서 YOURTYPE은 AssemblyInformationVersion 특성을 가진 Assembly의 임의의 유형입니다.

저는 이 질문이 단계별로 완벽한 답을 줄 가치가 있다고 생각합니다.여기서의 전략은 템플릿 파일을 가져와 git 태그 + 커밋 카운트 정보가 포함된 AssemblyInfo.cs 파일을 생성하는 빌드 전 이벤트에서 파워셸 스크립트를 실행하는 것입니다.

1단계: 어셈블리를 만듭니다.원래 AssemblyInfo.cs 을 기반으로 하지만 다음을 포함하는 Project\Properties 폴더의 Info_template.cs 파일.

[assembly: AssemblyVersion("$FILEVERSION$")]
[assembly: AssemblyFileVersion("$FILEVERSION$")]
[assembly: AssemblyInformationalVersion("$INFOVERSION$")]

2단계: InjectGitVersion.ps1이라는 이름의 파워셸 스크립트를 생성합니다.

# 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;       
}

3단계: InjectionGitVersion.ps1 파일을 BuildScripts 폴더의 솔루션 디렉토리에 저장합니다.

4단계: 프로젝트의 Pre-Build 이벤트에 다음 행 추가

powershell -ExecutionPolicy ByPass -File  $(SolutionDir)\BuildScripts\InjectGitVersion.ps1 $(ProjectDir)

5단계: 프로젝트를 구축합니다.

6단계: 선택적으로 git ignore 파일에 AssemblyInfo.cs 추가

이를 위한 또 다른 방법은 NetRevision을 사용하는 것입니다.On-Board Visual Studio 마법이 있는 도구입니다.Visual Studio 2013 Professional Edition을 위해 이 제품을 소개하지만 다른 버전에서도 사용할 수 있습니다.

먼저 NetRevision Tool을 다운로드합니다.NetRevisionTool.exe를 PATH에 포함하거나 저장소에 체크인한 후 비주얼 스튜디오 사전 빌드 및 빌드 후 작업을 생성하고 AssemblyInfo.cs 을 변경합니다.

Assembly Information Version에 git-hash를 추가하는 예는 다음과 같습니다.프로젝트 설정에서:

enter image description here

프로젝트의 AssemblyInfo.cs 에서 행을 변경/추가합니다.

[어셈블리:어셈블리 정보 버전("1.1.{dmin:2015.{chash:6}{!}-{branch})")]

표시된 스크린샷에서 외부/빈 폴더의 NetRevisionTool.exe에서 선택했습니다.

빌드 후 바이너리를 마우스 오른쪽 버튼으로 클릭하고 속성으로 이동하면 다음과 같은 것이 표시됩니다.

enter image description here

누군가에게 도움이 되길 바랍니다

여기 비주얼 스튜디오 2019에서 작동하며 깃 커밋 해시를 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;
}

변수 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>

확실히 .MyNameSpace두 파일 모두 당신의 요구에 부합합니다.서한은et한ee서stt 입니다.ItemGroupa에 끼워 넣어야 .Target게로AfterTargets세트.

이제 아주 쉬워졌습니다.MSBuild를 위한 NET 개정 작업 및 Visual Studio 2019와 함께 작업.

NuGet 패키지 Unclassified를 설치하기만 하면 됩니다.NetRevisionTask에서 원하는 정보를 구성합니다.AssemblyInfo.csGitHub 문서에 설명된 파일입니다.

마지막 커밋의 해시(length=8)만 원하는 경우:

[assembly: AssemblyInformationalVersion("1.0-{chash:8}")]

프로젝트/솔루션을 구축하면 다음과 같은 이점을 얻을 수 있습니다.

enter image description here

bit에 언급하고 , 에 했듯이 을 해 에서 를 해 을 에서 AssemblyInfo.cs프로젝트의 파일을 빌드 전 후크에 저장합니다.

이를 위한 한 가지 방법은AssemblyInfo.cs.tmpl템플릿 파일, SHA에 대한 자리 표시자(예: $$GITSHA$$).

[assembly: AssemblyDescription("$$GITSHA$$")]

그러면 사전 빌드 후크가 이 자리 표시자를 교체하고 C# 컴파일러가 선택할 수 있도록 AssemblyInfo.cs 파일을 출력해야 합니다.

SubWCrev for SVN을 사용하여 이 작업을 수행할 수 있는 방법은 다음 답변을 참조하십시오.비슷한 일을 하는 것은 어렵지 않을 것입니다.

다른 방법으로는 언급한 대로 "만들기 단계", 즉 유사한 작업을 수행하는 MSBuild 작업을 작성하는 것이 있습니다.또 다른 방법은 DLL을 어떻게든 후처리하는 것일 수도 있지만(idasm+ilasm say), 위에서 언급한 옵션이 아마도 가장 쉬울 것이라고 생각합니다.

완전 자동화되고 유연한 방법은 https://github.com/Fody/Stamp 에서 확인할 수 있습니다.Git 프로젝트에 이 버전을 성공적으로 사용했습니다(SVN 프로젝트에도 이 버전이 적용됨).

업데이트: 이것은 스탬프 이후로 구식입니다.Fody가 더 이상 유지되지 않습니다.

파워셸 원라이너를 사용하여 커밋 해시로 모든 assemblyinfo 파일을 업데이트할 수 있습니다.

$hash = git describe --long --always;gci **/AssemblyInfo.* -recurse | foreach { $content = (gc $_) -replace "\[assembly: Guid?.*", "$&`n[assembly: AssemblyMetadata(`"commithash`", `"$hash`")]" | sc $_ }

또 다른 방법은 Pre-Build 단계에서 Version.cs 파일을 생성하는 것입니다.저는 이것을 현재 커밋 해시를 출력하는 작은 개념 증명 프로젝트에서 탐구했습니다.

그 프로젝트는 https://github.com/sashoalm/GitCommitHashPrinter 에 업로드 됩니다.

Version.cs 파일을 만드는 배치 코드는 다음과 같습니다.

@echo off

echo "Writing Version.cs file..."

@rem Pushd/popd are used to temporarily cd to where the BAT file is.
pushd $(ProjectDir)

@rem Verify that the command succeeds (i.e. Git is installed and we are in the repo).
git rev-parse HEAD || exit 1

@rem Syntax for storing a command's output into a variable (see https://stackoverflow.com/a/2340018/492336).
@rem 'git rev-parse HEAD' returns the commit hash.
for /f %%i in ('git rev-parse HEAD') do set commitHash=%%i

@rem Syntax for printing multiline text to a file (see https://stackoverflow.com/a/23530712/492336).
(
echo namespace GitCommitHashPrinter
echo {
echo     class Version
echo     {
echo         public static string CommitHash { get; set; } = "%commitHash%";
echo     }
echo }
)>"Version.cs"

popd    
  1. 빌드 시 외부 프로그램 호출 및 출력 차단 방법을 알고 계시기 바랍니다.
  2. init의 작업 디렉토리가 버전이 없는 파일을 무시하도록 하는 방법을 아셨으면 좋겠습니다.

@의해 와 같이, @learath2의 와 한 은 에서, git rev-parse HEAD당신에게 평범한 해시를 줄 겁니다

Git-respository에서 태그를 사용하는 경우(그리고 태그를 사용하는 경우), 에서 출력을 수신할 수 있습니다(또한 나중에 성공적으로 사용됨).git checkout)

rev-parse를 호출할 수 있습니다.

  • 몇몇의 제작 단계
  • 커밋 후 훅으로
  • 번짐 필터에서 번짐/깨끗한 필터의 구현 방식을 선택할 경우
  • 를 ..csproj를 .<GenerateAssemblyInfo>false</GenerateAssemblyInfo>PropertyGroup
    • 이미 생성된 내용을 복사할 수 있습니다.AssemblyInfo.csobj폴더를 직접 작성할 필요가 없습니다.
  • 만들기AssemblyInfo.tt(T4 템플릿) 속성 폴더에 있습니다.
  • 다음 내용 + 이전에 자동으로 생성된 이전 내용을 붙여넣기AssemblyInfo.cs
<#@ template debug="true" hostspecific="True" language="C#" #>
<#@ assembly name="System.Core" #>
<# /*There's a bug with VS2022 where you have to be real specific about envDTE.*/ #>
<#@ assembly name="./PublicAssemblies/envdte.dll" #>  
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="System.Globalization" #>
<#@ output extension=".cs" #>
<#
    var dte = ((IServiceProvider)this.Host).GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
    string buildConfig = dte.Solution.SolutionBuild.ActiveConfiguration.Name;
    string solutionDirectory = Path.GetDirectoryName(dte.Solution.FullName);

    var (gitRevision, gitBranch, gitCompactRevision) = ("", "", "");

    using(var process = new System.Diagnostics.Process() {
        StartInfo = new System.Diagnostics.ProcessStartInfo() {
            WorkingDirectory = solutionDirectory,
            FileName = @"cmd.exe",
            Arguments = "/C git rev-parse HEAD & git rev-parse --abbrev-ref HEAD",
            RedirectStandardError = true,
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = true
        }
    }) {
        process.Start();
        string[] lines = process.StandardOutput.ReadToEnd().Split();
        gitRevision = lines[0].Trim();
        gitBranch = lines[1].Trim();
        gitCompactRevision = gitRevision.Substring(0, 6);
    }
    string appPurpose         = "Launcher"; // & Updater
    string companyShort       = "todo";
    string companyFull        = "todo";
    string productNameShort   = "todo";
    string productName        = $"{companyShort} {productNameShort}";
    string fileName           = $"{companyShort}{productNameShort}";
    string exeNAME            = $"{fileName}Launch";
    string originalFilename   = $"{exeNAME}.exe";
    string CALLEXE            = $"{fileName}.exe";
    string BROWSEREXE         = $"{fileName}Browser.exe";
    string FULLINSTALLER      = $"{fileName}Setup.exe";

    DateTime dtBuiltDate      = DateTime.UtcNow;
    string cBuildYear         = dtBuiltDate.Year.ToString();
    string cBuildDay          = dtBuiltDate.ToString("dd");
    string cBuildMonth        = dtBuiltDate.ToString("MM");
    string cBuildTime         = dtBuiltDate.ToString("T", DateTimeFormatInfo.InvariantInfo);
    string assemblyVersion    = $"3.0.{cBuildYear}.{cBuildMonth}{cBuildDay}";

    string JOB_NAME           = System.Environment.GetEnvironmentVariable("JOB_NAME") ?? "0.0";
    string buildVersion       = System.Environment.GetEnvironmentVariable("BUILD_NUMBER") ?? "0-dev";
    string buildSeries        = Regex.Replace(JOB_NAME, @"[^0-9\.]+", "");
    string buildNumber        = Regex.Replace(buildVersion, @"[^0-9\.]+", "");
    string InternalVersion    = $"{JOB_NAME}.{buildVersion}";
    string fileVersion        = Regex.Replace(InternalVersion, @"[^0-9\.]+", "");
#>
using System.Reflection;

[assembly: System.Runtime.InteropServices.ComVisible(false)]
[assembly: System.Resources.NeutralResourcesLanguageAttribute("en")]
[assembly: AssemblyConfigurationAttribute("<#= buildConfig #>")]
[assembly: AssemblyProduct("<#= productName #>")]
[assembly: AssemblyTitle("<#= $"{companyShort}{productNameShort}" #>")]
[assembly: AssemblyCompany("<#= companyFull #>")]
[assembly: AssemblyDescription("<#= $"{companyShort} {productNameShort} .... {appPurpose} - ...... by {companyFull}" #>")]
[assembly: AssemblyCopyright("<#= $"© 1983-{cBuildYear} {companyFull}" #>")]
[assembly: AssemblyTrademark("<#= $"{productName} is a trademark of {companyFull}, Inc." #>")]
[assembly: AssemblyInformationalVersion("<#= InternalVersion #>")]
[assembly: AssemblyVersion("<#= assemblyVersion #>")]
[assembly: AssemblyFileVersion("<#= fileVersion #>")]
[assembly: AssemblyMetadataAttribute("OriginalFilename",    "<#= originalFilename #>")]
[assembly: AssemblyMetadataAttribute("NAME",                "<#= $"{productName} {appPurpose}" #>")]
[assembly: AssemblyMetadataAttribute("EXENAME",             "<#= exeNAME #>")]
[assembly: AssemblyMetadataAttribute("DIRNAME",             "<#= productNameShort #>")]
[assembly: AssemblyMetadataAttribute("CALLEXE",             "<#= $"{fileName}.exe" #>")]
[assembly: AssemblyMetadataAttribute("BROWSEREXE",          "<#= $"{fileName}Browser.exe" #>")]
[assembly: AssemblyMetadataAttribute("FULLINSTALLER",       "<#= $"{fileName}Setup.exe" #>")]
[assembly: AssemblyMetadataAttribute("COMPANY",             "<#= companyFull #>")]
[assembly: AssemblyMetadataAttribute("License",             "<#= $"Contains copyrighted code and applications ..." #>")]
[assembly: AssemblyMetadataAttribute("TermsOfUse",          "<#= "https://www.company.com/en-us/terms-of-use/" #>")]
[assembly: AssemblyMetadataAttribute("Website",             "<#= "https://www.company.com/en-us" #>")]
[assembly: AssemblyMetadataAttribute("UpdateURL",           "https://subdomain.product.net/version_check")]

[assembly: AssemblyMetadataAttribute("BuildYear",           "<#= cBuildYear #>")]
[assembly: AssemblyMetadataAttribute("BuildDay",            "<#= cBuildDay #>")]
[assembly: AssemblyMetadataAttribute("BuildMonth",          "<#= cBuildMonth #>")]
[assembly: AssemblyMetadataAttribute("BuildTime",           "<#= cBuildTime #>")]
[assembly: AssemblyMetadataAttribute("DateModified",        "<#= $"{dtBuiltDate.ToString("MMM dd, yyyy", DateTimeFormatInfo.InvariantInfo)} at {cBuildTime}" #>")]

[assembly: AssemblyMetadataAttribute("BuildSeries",         "<#= buildSeries #>")]
[assembly: AssemblyMetadataAttribute("BuildNumber",         "<#= buildNumber #>")]
[assembly: AssemblyMetadataAttribute("BuildDate",           "<#= dtBuiltDate.ToString("s") #>")]
[assembly: AssemblyMetadataAttribute("BuildMachine",        "<#= Environment.MachineName #>")]
[assembly: AssemblyMetadataAttribute("BuildMachineUser",    "<#= Environment.UserName #>")]
[assembly: AssemblyMetadataAttribute("BuildOSVersion",      "<#= Environment.OSVersion #>")]
[assembly: AssemblyMetadataAttribute("BuildPlatform",       "<#= Environment.OSVersion.Platform #>")]
[assembly: AssemblyMetadataAttribute("BuildClrVersion",     "<#= Environment.Version #>")]

[assembly: AssemblyMetadataAttribute("BuildBranch",         "<#= gitBranch #>")]
[assembly: AssemblyMetadataAttribute("BuildRevision",       "<#= gitCompactRevision #>")]
[assembly: AssemblyMetadataAttribute("CommitHash",          "<#= gitRevision #>")]
[assembly: AssemblyMetadataAttribute("RepositoryUrl",       "")]
[assembly: AssemblyMetadataAttribute("RepositoryType",      "")]
<#+

#>

이제 C#의 풀 파워를 사용하여 현재 사용 중인 git 브랜치, 리비전 등 원하는 모든 것을 생성할 수 있습니다.몇 가지 팁:

  • 는 는 A 의 에서나 될 는 의 될 에서나 안<# #>
  • 은 파일 하고자 는 의 에 되어야 되어야 하고자 에 <#+ #> (록.)+사인은 매우 중요하며 파일의 마지막에 표시되어야 합니다.)
  • <# #>blocks는 그냥 평문입니다.
  • VS2019는 구문 강조나 지능이 없습니다..ttfile은 평문입니다.i를 설치한 후에 vScode로 편집하는 것을 합니다.T4 Support확장(vs2019에서 사용할 수 없음...)

한 줄, , 만에 대한 Microsoft.SourceLink.GitHub

    <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />

git commit hash는 에 자동으로 포함됩니다.망 dll.

자세한 내용은 문서 참조

저는 합격된 답변과 약간의 추가사항을 조합해서 사용하고 있습니다.빌드 전 템플릿을 다시 실행하기 위해 AutoT4 확장(https://marketplace.visualstudio.com/items?itemName=BennorMcCarthy.AutoT4) 을 설치했습니다.

Git에서 버전 가져오기

있습니다git -C $(ProjectDir) describe --long --always > "$(ProjectDir)git_version.txt"프로젝트 부동산의 건설 전 이벤트에서 말입니다..git_version.하는을s 을 추가하는 은 꽤 입니다txt와 VersionInfo.cs 에서 .gitignore 는 꽤 생각입니다 좋은 생각입니다 는 좋은 t . 꽤 xt to ore git .

메타데이터에 버전 포함

를 했습니다.VersionInfo.tt프로젝트 템플릿:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#@ output extension=".cs" #>

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

<#
if (File.Exists(Host.ResolvePath("git_version.txt")))
{
    Write("[assembly: AssemblyInformationalVersion(\""+ File.ReadAllText(Host.ResolvePath("git_version.txt")).Trim() + "\")]");
}else{
    Write("// version file not found in " + Host.ResolvePath("git_version.txt"));
}

#>

이제 "ProductVersion"에 git tag + hash가 있습니다.

다른 답변을 참고하여(https://stackoverflow.com/a/44278482/4537127) 또한 다음과 같이 활용했습니다.VersionInfo.tt할트릿릿트할AssemblyInformationalVersion자동 T4가 없는 경우

(적어도 내 C# WPF 응용 프로그램에서 작동)

문제는 사전 빌드 이벤트가 템플릿 변환 후에 실행되므로 클로닝 후에git_version.txt파일이 존재하지 않아 빌드가 실패합니다.변환을 한 번만 통과할 수 있도록 수동으로 생성한 후 변환 후 업데이트되었으며 항상 한 번의 커밋이 뒤에 있었습니다.

.csproj 파일을 두 번 수정해야 했습니다. (이것은 적어도 Visual Studio Community 2017에 적용됩니다.)

1) 텍스트 변환 대상을 가져오고 모든 빌드에서 실행할 템플릿 변환: (https://msdn.microsoft.com/en-us/library/ee847423.aspx) 참조)

<PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
    <TransformOnBuild>true</TransformOnBuild>
    <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
</PropertyGroup>

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

<Import Project="$(VSToolsPath)\TextTemplating\Microsoft.TextTemplating.targets" />

the 2) git describe 변환을기에행을 를)).git_version.txt언제 거기에 있습니까?VersionInfo.ttcyclic):

<Target Name="PreBuild" BeforeTargets="ExecuteTransformations">
  <Exec Command="git -C $(ProjectDir) describe --long --always --dirty &gt; $(ProjectDir)git_version.txt" />
</Target>

..그리고 C# 코드는AssemblyInformationalVersion(https://stackoverflow.com/a/7770189/4537127) 참조

public string AppGitHash
{
    get
    {
        AssemblyInformationalVersionAttribute attribute = (AssemblyInformationalVersionAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false).FirstOrDefault();

        return attribute.InformationalVersion;
    }
}

..그리고 생성된 파일을 .gitignore에 추가합니다.

VersionInfo.cs
git_version.txt

장소

<Target Name="UpdateVersion" BeforeTargets="CoreCompile">
  <Exec Command="php &quot;$(SolutionDir)build.php&quot; $(SolutionDir) &quot;$(ProjectDir)Server.csproj&quot;" />
</Target>

인에YOUR_PROJECT_NAME.csproj

<?php

function between(string $string, string $after, string $before, int $offset = 0) : string{
    return substr($string, $pos = strpos($string, $after, $offset) + strlen($after),
        strpos($string, $before, $pos) - $pos);
}

$pipes = [];
$proc = proc_open("git rev-parse --short HEAD", [
    0 => ["pipe", "r"],
    1 => ["pipe", "w"],
    2 => ["pipe", "w"]
], $pipes, $argv[1]);

if(is_resource($proc)){
    $rev = stream_get_contents($pipes[1]);
    proc_close($proc);
}

$manifest = file_get_contents($argv[2]);
$version = between($manifest, "<Version>", "</Version>");
$ver = explode("-", $version)[0] . "-" . trim($rev);
file_put_contents($argv[2], str_replace($version, $ver, $manifest));

echo "New version generated: $ver" . PHP_EOL;

@John Jesus answer에서 큰 영감을 받아, 나는 조립 버전을 현재 Git 태그로 조정하기 위해 각 빌드에서 실행되는 파워셸 v1 스크립트를 만들었습니다.

파워셸 대본

# Get build running directory
$scriptPath = split-path -parent $MyInvocation.MyCommand.Path
try {
    $v = git describe --tags
}
catch [System.Management.Automation.CommandNotFoundException] {
    # Git not found
    exit
}

# Letters are incompatible with AssemblyVersion.cs so we remove them
$v = $v -replace "v", ""
# Version format is major[.minor[.build[.revision]] so we remove them
$v = $v -replace "-(\D.*)", ''
$v = $v -replace "-", '.'

# We replace versions inside AssemblyInfo.cs content
$info = (Get-Content ($scriptPath + "/properties/AssemblyInfo.cs"))
$av = '[assembly: AssemblyVersion("'+$v+'")]'
$avf = '[assembly: AssemblyFileVersion("'+$v+'")]'
$info = $info -replace '\[assembly: AssemblyVersion\("(.*)"\)]', $av
$info = $info -replace '\[assembly: AssemblyFileVersion\("(.*)"\)]', $avf
Set-Content -Path ($scriptPath + "/properties/AssemblyInfo.cs") -Value $info -Encoding UTF8

솔루션 폴더에 저장하고 Prebuild Event를 설정하여 실행합니다.

다음 파일을 개발/스테이지 시스템에 배포하여 간단히 확인합니다.

git.exe -C "$(ProjectDir.TrimEnd('\'))" describe --long > "$(ProjectDir)_Version.info":

내 결과: 10.02.0.3-247-gbeadd082

git.exe -C "$(ProjectDir.TrimEnd('\'))" branch --show-current > "$(ProjectDir)_Branch.info"

내 결과: 피쳐/JMT-3931-jaguar

(Visual Studio PreBuild 이벤트)

더 편리하게 추가할 수 있는 방법을 찾았습니다.

<ItemGroup>
    <PackageReference Include="GitVersion.MsBuild" Version="5.10.3">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
</ItemGroup>

.csproj. 이것은 매우 유연한 GitVersion 툴 위에 구축됩니다.

이것은 다음을 설정합니다.Product Version생성에서 어떤 다음 작성하여 제어 있습니다 같이 정보출력할지 a 있습니다 creating which by ation to inform control output be 에서 you 생성 can dll 어떤 제어정보작성하여 출력할지다음같이GitVersion.yml파일이 들어 있는

assembly-informational-format: '{Sha}'

다른 형식도 있습니다.GitVersion 설명서의 Version 변수에 나열되어 있습니다.

다른 옵션은 마이크로소프트가 자체적으로 제공하는 소스링크를 사용하는 것입니다.하지만 솔직히 이 접근 방식에서 많은 특이점과 제한점을 발견했습니다(예: SourceLinks는 레포가 어디에서 호스팅되는지 알고 싶어하고, Azure DevOps, GitHub, GitLab, BitBucket, gitea 등에 따라 다르게 구성해야 하는 것 같습니다).

언급URL : https://stackoverflow.com/questions/15141338/embed-git-commit-hash-in-a-net-dll

반응형