문제

현재 제목 창에 빌드 번호를 표시하는 앱이 있습니다.최신 빌드가 있는지 알고 싶어하는 대부분의 사용자에게 아무 의미가 없다는 점을 제외하면 이는 훌륭하고 좋습니다. 그들은 이를 빌드 1.0.8.4321이 아닌 "지난 목요일"이라고 부르는 경향이 있습니다.

계획은 대신 빌드 날짜를 입력하는 것입니다. 예를 들어 "2009년 10월 21일에 빌드된 앱"입니다.

이와 같이 사용하기 위해 빌드 날짜를 텍스트 문자열로 추출하는 프로그래밍 방식을 찾는 데 어려움을 겪고 있습니다.

빌드 번호로는 다음을 사용했습니다.

Assembly.GetExecutingAssembly().GetName().Version.ToString()

그 일이 어떻게 일어 났는지 정의한 후.

컴파일 날짜(및 시간, 보너스 포인트)에 대해 이와 같은 것을 원합니다.

여기에 대한 포인터는 매우 감사합니다(해당하는 경우 말장난을 용서하세요). 또는 더 깔끔한 솔루션입니다...

도움이 되었습니까?

해결책

Jeff Atwood는이 문제에 대해 몇 가지 말을했습니다. 빌드 날짜 결정 어려운 방법.

가장 신뢰할 수있는 방법은 PE 헤더 실행 파일에 내장 - 주석에서 Jeff의 기사에 이르기까지 일부 C# 코드 (Joe Spivey) :

public static DateTime GetLinkerTime(this Assembly assembly, TimeZoneInfo target = null)
{
    var filePath = assembly.Location;
    const int c_PeHeaderOffset = 60;
    const int c_LinkerTimestampOffset = 8;

    var buffer = new byte[2048];

    using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        stream.Read(buffer, 0, 2048);

    var offset = BitConverter.ToInt32(buffer, c_PeHeaderOffset);
    var secondsSince1970 = BitConverter.ToInt32(buffer, offset + c_LinkerTimestampOffset);
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    var linkTimeUtc = epoch.AddSeconds(secondsSince1970);

    var tz = target ?? TimeZoneInfo.Local;
    var localTime = TimeZoneInfo.ConvertTimeFromUtc(linkTimeUtc, tz);

    return localTime;
}

사용 예 :

var linkTimeLocal = Assembly.GetExecutingAssembly().GetLinkerTime();

업데이트 :이 방법은 .NET Core 1.0에서 작동했지만 .NET Core 1.1 이후 작동이 중지되었습니다 릴리스 (1900-2020 년 범위의 임의 연도)

다른 팁

예비 건축 이벤트 명령 줄에 아래를 추가하십시오.

echo %date% %time% > "$(ProjectDir)\Resources\BuildDate.txt"

이 파일을 리소스로 추가하십시오. 이제 리소스에 'BuildDate'문자열이 있습니다.

리소스를 만들려면 참조하십시오 .NET에서 리소스를 생성하고 사용하는 방법.

@c00000fd에서 지적한 바와 같이 코멘트. Microsoft가 이것을 바꾸고 있습니다. 그리고 많은 사람들이 최신 버전의 컴파일러를 사용하지 않지만이 변화는이 접근법이 의심 할 여지없이 나쁘다고 생각합니다. 그리고 재미있는 운동이지만 이진 자체의 빌드 날짜를 추적하는 것이 중요하다면 사람들이 다른 방법을 통해 바이너리에 빌드 날짜를 포함시키는 것이 좋습니다.

이것은 이미 빌드 스크립트의 첫 번째 단계 인 사소한 코드 생성으로 수행 할 수 있습니다. 그리고 ALM/Build/DevOps 도구가 이것에 많은 도움이되며 다른 어떤 것보다 선호되어야한다는 사실.

나는이 답의 나머지 부분을 여기에 역사적 목적으로 만 남긴다.

새로운 방법

나는 이것에 대해 마음을 바꾸었고 현재이 트릭을 사용하여 올바른 빌드 날짜를 얻습니다.

#region Gets the build date and time (by reading the COFF header)

// http://msdn.microsoft.com/en-us/library/ms680313

struct _IMAGE_FILE_HEADER
{
    public ushort Machine;
    public ushort NumberOfSections;
    public uint TimeDateStamp;
    public uint PointerToSymbolTable;
    public uint NumberOfSymbols;
    public ushort SizeOfOptionalHeader;
    public ushort Characteristics;
};

static DateTime GetBuildDateTime(Assembly assembly)
{
    var path = assembly.GetName().CodeBase;
    if (File.Exists(path))
    {
        var buffer = new byte[Math.Max(Marshal.SizeOf(typeof(_IMAGE_FILE_HEADER)), 4)];
        using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
        {
            fileStream.Position = 0x3C;
            fileStream.Read(buffer, 0, 4);
            fileStream.Position = BitConverter.ToUInt32(buffer, 0); // COFF header offset
            fileStream.Read(buffer, 0, 4); // "PE\0\0"
            fileStream.Read(buffer, 0, buffer.Length);
        }
        var pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        try
        {
            var coffHeader = (_IMAGE_FILE_HEADER)Marshal.PtrToStructure(pinnedBuffer.AddrOfPinnedObject(), typeof(_IMAGE_FILE_HEADER));

            return TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1) + new TimeSpan(coffHeader.TimeDateStamp * TimeSpan.TicksPerSecond));
        }
        finally
        {
            pinnedBuffer.Free();
        }
    }
    return new DateTime();
}

#endregion

오래된 방법

글쎄, 빌드 숫자를 어떻게 생성합니까? Visual Studio (또는 C# 컴파일러)는 실제로 AssemblyVersion 속성을 EG로 변경하면 자동 빌드 및 개정 번호를 제공합니다. 1.0.*

이런 일은 빌드가 2000 년 1 월 1 일 현지 시간 이후 일수와 같을 것이며, 개정은 현지 시간 이후 2 초과 동일하며 2로 나눈 것입니다.

커뮤니티 콘텐츠보기, 자동 빌드 및 개정 번호

예 : AssemblyInfo.cs

[assembly: AssemblyVersion("1.0.*")] // important: use wildcard for build and revision numbers!

SampleCode.cs

var version = Assembly.GetEntryAssembly().GetName().Version;
var buildDateTime = new DateTime(2000, 1, 1).Add(new TimeSpan(
TimeSpan.TicksPerDay * version.Build + // days since 1 January 2000
TimeSpan.TicksPerSecond * 2 * version.Revision)); // seconds since midnight, (multiply by 2 to get original)

예비 건축 이벤트 명령 줄에 아래를 추가하십시오.

echo %date% %time% > "$(ProjectDir)\Resources\BuildDate.txt"

이 파일을 리소스로 추가하십시오. 이제 리소스에 'BuildDate'문자열이 있습니다.

파일을 리소스에 삽입 한 후 (공개 텍스트 파일)

string strCompTime = Properties.Resources.BuildDate;

리소스를 만들려면 참조하십시오 .NET에서 리소스를 생성하고 사용하는 방법.

아직 아무도 언급하지 않은 접근법 중 하나는 다음과 같습니다. T4 텍스트 템플릿 코드 생성을 위해.

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System" #>
<#@ output extension=".g.cs" #>
using System;
namespace Foo.Bar
{
    public static partial class Constants
    {
        public static DateTime CompilationTimestampUtc { get { return new DateTime(<# Write(DateTime.UtcNow.Ticks.ToString()); #>L, DateTimeKind.Utc); } }
    }
}

장점:

  • 로케일 독립적
  • 컴파일 시간보다 더 많은 것을 허용합니다.

단점:

어셈블리 PE 헤더의 바이트에서 빌드 날짜/버전 정보를 끌어내는 기술과 관련하여 Microsoft는 Visual Studio 15.4로 시작하는 기본 빌드 매개 변수를 변경했습니다. 새로운 기본값에는 결정 론적 컴파일이 포함되어있어 유효한 타임 스탬프를 만들고 버전 번호를 자동으로 증가시킵니다. 타임 스탬프 필드는 여전히 존재하지만 무언가 또는 기타의 해시 인 영구 값으로 채워 지지만 빌드 시간의 표시는 아닙니다.

여기에 자세한 배경

결정 론적 편집보다 유용한 타임 스탬프를 우선시하는 사람들에게는 새로운 기본값을 무시할 수있는 방법이 있습니다. 관심있는 어셈블리의 .csproj 파일에 태그를 다음과 같이 포함시킬 수 있습니다.

  <PropertyGroup>
      ...
      <Deterministic>false</Deterministic>
  </PropertyGroup>

업데이트 : 여기에서 다른 답변에 설명 된 T4 텍스트 템플릿 솔루션을 보증합니다. 결정 론적 편집의 이점을 잃지 않고 문제를 깨끗하게 해결하는 데 사용했습니다. 한 가지주의는 Visual Studio가 빌드 타임이 아닌 .tt 파일이 저장 될 때만 T4 컴파일러 만 실행한다는 것입니다. 소스 컨트롤에서 .CS 결과를 제외하고 (생성 될 것으로 예상되기 때문에) 다른 개발자가 코드를 확인하면 어색 할 수 있습니다. 재조정하지 않으면 .CS 파일이 없습니다. NUGET (Autot4라고 함)에는 T4 컴파일이 모든 빌드의 일부를 만드는 패키지가 있습니다. 나는 생산 배치 중에 아직이 문제에 대한 해결책에 직면하지 않았지만 비슷한 것이 올바르게 만들 것으로 기대합니다.

나는 단지 C# nevbie이므로 내 대답 소리가 어리석은 것일 수도 있습니다. 실행 파일이 마지막으로 작성된 날짜부터 빌드 날짜를 표시합니다.

string w_file = "MyProgram.exe"; 
string w_directory = Directory.GetCurrentDirectory();

DateTime c3 =  File.GetLastWriteTime(System.IO.Path.Combine(w_directory, w_file));
RTB_info.AppendText("Program created at: " + c3.ToString());

File.getCreationTime 메서드를 사용하려고했지만 이상한 결과를 얻었습니다. 명령의 날짜는 2012-05-29이지만 Window Explorer의 날짜는 2012-05-23을 보여주었습니다. 이 불일치를 검색 한 후 파일이 2012-05-23 (Windows Explorer가 표시 함)에 생성되었지만 2012-05-29의 현재 폴더에 복사 한 것으로 나타났습니다 (file.getCreationTime 명령)- 안전한 측면에 있으려면 파일을 사용하고 있습니다. getLastWritetime 명령.

Zalek

Windows 8 / Windows Phone 8에서 컴파일 시간을 가져와야하는 사람은 누구나 : 8 :

    public static async Task<DateTimeOffset?> RetrieveLinkerTimestamp(Assembly assembly)
    {
        var pkg = Windows.ApplicationModel.Package.Current;
        if (null == pkg)
        {
            return null;
        }

        var assemblyFile = await pkg.InstalledLocation.GetFileAsync(assembly.ManifestModule.Name);
        if (null == assemblyFile)
        {
            return null;
        }

        using (var stream = await assemblyFile.OpenSequentialReadAsync())
        {
            using (var reader = new DataReader(stream))
            {
                const int PeHeaderOffset = 60;
                const int LinkerTimestampOffset = 8;

                //read first 2048 bytes from the assembly file.
                byte[] b = new byte[2048];
                await reader.LoadAsync((uint)b.Length);
                reader.ReadBytes(b);
                reader.DetachStream();

                //get the pe header offset
                int i = System.BitConverter.ToInt32(b, PeHeaderOffset);

                //read the linker timestamp from the PE header
                int secondsSince1970 = System.BitConverter.ToInt32(b, i + LinkerTimestampOffset);

                var dt = new DateTimeOffset(1970, 1, 1, 0, 0, 0, DateTimeOffset.Now.Offset) + DateTimeOffset.Now.Offset;
                return dt.AddSeconds(secondsSince1970);
            }
        }
    }

Windows Phone 7에서 컴파일 시간을 가져와야하는 사람은 누구나 :

    public static async Task<DateTimeOffset?> RetrieveLinkerTimestampAsync(Assembly assembly)
    {
        const int PeHeaderOffset = 60;
        const int LinkerTimestampOffset = 8;            
        byte[] b = new byte[2048];

        try
        {
            var rs = Application.GetResourceStream(new Uri(assembly.ManifestModule.Name, UriKind.Relative));
            using (var s = rs.Stream)
            {
                var asyncResult = s.BeginRead(b, 0, b.Length, null, null);
                int bytesRead = await Task.Factory.FromAsync<int>(asyncResult, s.EndRead);
            }
        }
        catch (System.IO.IOException)
        {
            return null;
        }

        int i = System.BitConverter.ToInt32(b, PeHeaderOffset);
        int secondsSince1970 = System.BitConverter.ToInt32(b, i + LinkerTimestampOffset);
        var dt = new DateTimeOffset(1970, 1, 1, 0, 0, 0, DateTimeOffset.Now.Offset) + DateTimeOffset.Now.Offset;
        dt = dt.AddSeconds(secondsSince1970);
        return dt;
    }

참고 : 모든 경우에 샌드 박스에서 실행되므로 앱과 함께 배포하는 어셈블리의 컴파일 시간 만 얻을 수 있습니다. (즉, 이것은 GAC에서 아무것도 작동하지 않습니다).

위의 방법은 어셈블리에 대해 조정할 수 있습니다 프로세스 내에서 이미로드되었습니다 메모리에서 파일의 이미지를 사용하여 (스토리지에서 다시 읽는 것과 반대로) :

using System;
using System.Runtime.InteropServices;
using Assembly = System.Reflection.Assembly;

static class Utils
{
    public static DateTime GetLinkerDateTime(this Assembly assembly, TimeZoneInfo tzi = null)
    {
        // Constants related to the Windows PE file format.
        const int PE_HEADER_OFFSET = 60;
        const int LINKER_TIMESTAMP_OFFSET = 8;

        // Discover the base memory address where our assembly is loaded
        var entryModule = assembly.ManifestModule;
        var hMod = Marshal.GetHINSTANCE(entryModule);
        if (hMod == IntPtr.Zero - 1) throw new Exception("Failed to get HINSTANCE.");

        // Read the linker timestamp
        var offset = Marshal.ReadInt32(hMod, PE_HEADER_OFFSET);
        var secondsSince1970 = Marshal.ReadInt32(hMod, offset + LINKER_TIMESTAMP_OFFSET);

        // Convert the timestamp to a DateTime
        var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        var linkTimeUtc = epoch.AddSeconds(secondsSince1970);
        var dt = TimeZoneInfo.ConvertTimeFromUtc(linkTimeUtc, tzi ?? TimeZoneInfo.Local);
        return dt;
    }
}

여기서 논의되지 않은 옵션은 자신의 데이터를 AssemblyInfo.cs에 삽입하는 것입니다. "AssemblyInformationalVersion"필드는 적절 해 보입니다. 우리는 빌드 단계와 비슷한 일을하는 몇 가지 프로젝트가 있습니다 (그러나 나는 완전히 만족하지 않습니다. 작동하는 방식이므로 우리가 가진 것을 실제로 재현하고 싶지는 않습니다).

CodeProject의 주제에 관한 기사가 있습니다. http://www.codeproject.com/kb/dotnet/customizing_csproj_files.aspx

.NET Core Projects의 경우 Build 날짜와 함께 조립 저작권 필드를 업데이트하기 위해 PostLagerkarte의 답변을 조정했습니다.

CSPROJ를 직접 편집합니다

다음은 첫 번째에 직접 추가 할 수 있습니다 PropertyGroup CSPROJ에서 :

<Copyright>Copyright © $([System.DateTime]::UtcNow.Year) Travis Troyer ($([System.DateTime]::UtcNow.ToString("s")))</Copyright>

대안 : Visual Studio Project 속성

또는 Visual Studio의 프로젝트 속성의 패키지 섹션에서 내부 표현식을 저작권 필드에 직접 붙여 넣습니다.

Copyright © $([System.DateTime]::UtcNow.Year) Travis Troyer ($([System.DateTime]::UtcNow.ToString("s")))

Visual Studio가 표현식을 평가하고 창에 현재 값을 표시하기 때문에 이것은 약간 혼란 스러울 수 있지만 장면 뒤에서 프로젝트 파일을 적절하게 업데이트합니다.

directory.build.props를 통해 솔루션 전체

당신은 <Copyright> 위의 요소로의 요소 Directory.Build.props 솔루션 루트에 파일을 파일하고 각 프로젝트가 자체 저작권 값을 제공하지 않는다고 가정 할 때 디렉토리 내의 모든 프로젝트에 자동으로 적용되도록하십시오.

<Project>
 <PropertyGroup>
   <Copyright>Copyright © $([System.DateTime]::UtcNow.Year) Travis Troyer ($([System.DateTime]::UtcNow.ToString("s")))</Copyright>
 </PropertyGroup>
</Project>

directory.build.props : 빌드를 사용자 정의하십시오

산출

예제 표현식은 다음과 같은 저작권을 제공합니다.

Copyright © 2018 Travis Troyer (2018-05-30T14:46:23)

검색

Windows의 파일 속성에서 저작권 정보를 보거나 런타임에 가져올 수 있습니다.

var version = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location);

Console.WriteLine(version.LegalCopyright);

여기에 많은 훌륭한 답변이 있지만 단순성, 성능 (리소스 관련 솔루션과 비교) 크로스 플랫폼 (Net Core와 함께 작동) 및 타사 도구를 피할 수 있다고 생각합니다. 이 MSBuild 대상을 CSPROJ에 추가하십시오.

<Target Name="Date" BeforeTargets="CoreCompile">
    <WriteLinesToFile File="$(IntermediateOutputPath)gen.cs" Lines="static partial class Builtin { public static long CompileTime = $([System.DateTime]::UtcNow.Ticks) %3B }" Overwrite="true" />
    <ItemGroup>
        <Compile Include="$(IntermediateOutputPath)gen.cs" />
    </ItemGroup>
</Target>

그리고 지금 당신은 가지고 있습니다 Builtin.CompileTime 또는 new DateTime(Builtin.CompileTime, DateTimeKind.Utc) 그런 식으로 필요하다면.

Resharper는 그것을 좋아하지 않을 것입니다. 당신은 그를 무시하거나 프로젝트에 부분 수업을 추가 할 수 있지만 어쨌든 작동합니다.

2018 년에 위의 일부 솔루션 중 일부는 더 이상 작동하지 않거나 .NET Core에서 작동하지 않습니다.

간단하고 .NET Core 2.0 프로젝트에서 작동하는 다음 접근 방식을 사용합니다.

속성 그룹 내부의 .csproj에 다음을 추가하십시오.

    <Today>$([System.DateTime]::Now)</Today>

이것은 a를 정의합니다 속성 기능 사전 빌드 명령에서 액세스 할 수 있습니다.

당신의 사전 건축은 다음과 같습니다

echo $(today) > $(ProjectDir)BuildTimeStamp.txt

BuildTimestamp.txt의 속성을 임베디드 리소스로 설정하십시오.

이제 이와 같은 타임 스탬프를 읽을 수 있습니다

public static class BuildTimeStamp
    {
        public static string GetTimestamp()
        {
            var assembly = Assembly.GetEntryAssembly(); 

            var stream = assembly.GetManifestResourceStream("NamespaceGoesHere.BuildTimeStamp.txt");

            using (var reader = new StreamReader(stream))
            {
                return reader.ReadToEnd();
            }
        }
    }

모든 플랫폼 (iOS, Android 및 Windows)에서 Netstandard 프로젝트와 함께 작동하는 범용 솔루션이 필요했습니다.이를 수행하기 위해 PowerShell 스크립트를 통해 CS 파일을 자동으로 생성하기로 결정했습니다. PowerShell 스크립트는 다음과 같습니다.

param($outputFile="BuildDate.cs")

$buildDate = Get-Date -date (Get-Date).ToUniversalTime() -Format o
$class = 
"using System;
using System.Globalization;

namespace MyNamespace
{
    public static class BuildDate
    {
        public const string BuildDateString = `"$buildDate`";
        public static readonly DateTime BuildDateUtc = DateTime.Parse(BuildDateString, null, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
    }
}"

Set-Content -Path $outputFile -Value $class

PowerScript 파일을 GenBuildDate.ps1로 저장하고 프로젝트를 추가하십시오. 마지막으로 건축 사전 이벤트에 다음 줄을 추가하십시오.

powershell -File $(ProjectDir)GenBuildDate.ps1 -outputFile $(ProjectDir)BuildDate.cs

BuildDate.cs가 프로젝트에 포함되어 있는지 확인하십시오. 모든 OS에서 챔피언처럼 작동합니다!

나는 단지한다 :

File.GetCreationTime(GetType().Assembly.Location)

이 프로젝트를 사용할 수 있습니다. https://github.com/dwcullop/buildinfo

T4를 활용하여 빌드 날짜 타임 스탬프를 자동화합니다. 당신이 그런 종류의 일이 있다면, 현재 체크 아웃 된 지점의 git 해시를 제공하는 것을 포함하여 여러 버전 (다른 분기)이 있습니다.

공개 : 모듈을 썼습니다.

프로젝트 포스트 빌드 이벤트를 사용하여 현재 DateTime과 함께 대상 디렉토리에 텍스트 파일을 작성할 수 있습니다. 그런 다음 런타임에서 값을 읽을 수 있습니다. 약간 해킹되지만 작동해야합니다.

확실하지 않지만 아마도 증분을 빌드하십시오 도움이됩니다.

다르고 PCL 친화적 인 접근 방식은 MSBuild Inline 작업을 사용하여 빌드 시간을 앱의 속성에 의해 반환되는 문자열로 대체하는 것입니다. 우리는 Xamarin.forms, Xamarin.Android 및 Xamarin.ios 프로젝트가있는 앱 에서이 접근법을 성공적으로 사용하고 있습니다.

편집하다:

모든 논리를 SetBuildDate.targets 파일 및 사용 Regex 간단한 문자열 대신 "재설정"없이 각 빌드에서 파일을 수정할 수 있도록 교체하십시오.

MSBuild Inline 작업 정의 (SetBuildDate.targets 파일에 저장된 Xamarin.forms 프로젝트에 로컬) :

<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion="12.0">

  <UsingTask TaskName="SetBuildDate" TaskFactory="CodeTaskFactory" 
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
    <ParameterGroup>
      <FilePath ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Code Type="Fragment" Language="cs"><![CDATA[

        DateTime now = DateTime.UtcNow;
        string buildDate = now.ToString("F");
        string replacement = string.Format("BuildDate => \"{0}\"", buildDate);
        string pattern = @"BuildDate => ""([^""]*)""";
        string content = File.ReadAllText(FilePath);
        System.Text.RegularExpressions.Regex rgx = new System.Text.RegularExpressions.Regex(pattern);
        content = rgx.Replace(content, replacement);
        File.WriteAllText(FilePath, content);
        File.SetLastWriteTimeUtc(FilePath, now);

   ]]></Code>
    </Task>
  </UsingTask>

</Project>

Xamarin.forms CSPROJ 파일에서 위의 인라인 작업을 대상 이전에 대상 작업 :

  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.  -->
  <Import Project="SetBuildDate.targets" />
  <Target Name="BeforeBuild">
    <SetBuildDate FilePath="$(MSBuildProjectDirectory)\BuildMetadata.cs" />
  </Target>

그만큼 FilePath 속성은 a로 설정됩니다 BuildMetadata.cs 문자열 속성이있는 간단한 클래스가 포함 된 xamarin.forms 프로젝트의 파일 BuildDate, 빌드 시간을 대체 할 :

public class BuildMetadata
{
    public static string BuildDate => "This can be any arbitrary string";
}

이 파일을 추가하십시오 BuildMetadata.cs 프로젝트에. 모든 빌드에 의해 수정되지만 반복 된 빌드 (반복 교체)를 허용하는 방식으로 원하는대로 소스 제어에 포함 시키거나 생략 할 수 있습니다.

Jhon의 "New Way"답변에 대한 작은 업데이트.

asp.net/mvc와 함께 작업 할 때 Codebase 문자열을 사용하는 대신 경로를 구축해야합니다.

    var codeBase = assembly.GetName().CodeBase;
    UriBuilder uri = new UriBuilder(codeBase);
    string path = Uri.UnescapeDataString(uri.Path);

빌드 프로세스에서 추가 단계를 시작하여 날짜 스탬프를 파일에 기록한 다음 표시 할 수 있습니다.

프로젝트 속성 탭에서 빌드 이벤트 탭을보십시오. 사전 또는 사후 빌드 명령을 실행할 수있는 옵션이 있습니다.

Abdurrahim의 제안을 사용했습니다. 그러나 이상한 시간 형식을 제공하는 것처럼 보였고 빌드 날짜의 일부로 하루의 약어를 추가했습니다. 예 : Sun 12/24/2017 13 : 21 : 05.43. 날짜 만 필요했기 때문에 하위 문자열을 사용하여 나머지를 제거해야했습니다.

추가 한 후 echo %date% %time% > "$(ProjectDir)\Resources\BuildDate.txt"건축 사전 이벤트에 다음을 수행했습니다.

string strBuildDate = YourNamespace.Properties.Resources.BuildDate;
string strTrimBuildDate = strBuildDate.Substring(4).Remove(10);

여기서 좋은 소식은 그것이 효과가 있다는 것입니다.

이것이 Windows 앱 인 경우 응용 프로그램 실행 경로를 사용할 수 있습니다 : new System.io.FileInfo (application.ExecutablePath) .lastWriteTime.toString ( "yyyy.mm.dd").

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top