현재 제목 창에 빌드 번호를 표시하는 앱이 있습니다. 최신 빌드가 있는지 알고 싶어하는 대부분의 사용자에게는 아무런 의미가 없다는 점을 제외하고는 훌륭합니다. 빌드 1.0.8.4321이 아니라 “마지막 목요일”이라고 말하는 경향이 있습니다.
계획은 빌드 날짜를 대신하는 것입니다-예를 들어 “App built on 21/10/2009”.
빌드 날짜를 텍스트 문자열로 사용하여 프로그래밍 방식을 사용하는 프로그래밍 방식을 찾는 데 어려움을 겪고 있습니다.
빌드 번호에는 다음을 사용했습니다.
Assembly.GetExecutingAssembly().GetName().Version.ToString()
그 방법을 정의한 후.
컴파일 날짜 (및 보너스 포인트 시간)와 같은 것을 원합니다.
여기의 포인터는 (해당되는 경우 변명) 또는 더 좋은 해결책을 높이 평가했습니다 …
답변
Jeff Atwood는 빌드 날짜 결정 에서이 문제에 대해 할 말이별로 없었습니다 .
가장 신뢰할 수있는 방법은 실행 파일에 포함 된 PE 헤더 에서 링커 타임 스탬프를 검색하는 것으로 나타났습니다 .
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가 지적한대로 . 마이크로 소프트는 이것을 바꾸고있다. 많은 사람들이 최신 버전의 컴파일러를 사용하지 않지만이 변경으로 인해이 접근법이 의심 할 여지없이 나쁘다고 생각합니다. 그리고 재미있는 연습이지만 사람들이 바이너리 자체의 빌드 날짜를 추적하는 것이 중요하다면 필요한 다른 수단을 통해 빌드 날짜를 바이너리에 간단히 삽입하는 것이 좋습니다.
이것은 아마도 빌드 스크립트의 첫 번째 단계 일 수있는 사소한 코드 생성으로 수행 될 수 있습니다. 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
옛날 방식
글쎄, 어떻게 빌드 번호를 생성합니까? AssemblyVersion 특성을 다음과 같이 변경하면 Visual Studio (또는 C # 컴파일러)는 실제로 자동 빌드 및 수정 번호를 제공합니다.1.0.*
일어날 일은 2000 년 1 월 1 일 현지 시간 이후의 일 수와 같고 수정이 현지 시간 자정 이후의 초 수와 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); } }
}
}
장점 :
- 로케일 독립적
- 컴파일 시간보다 더 많은 것을 허용
단점 :
- 소스를 제어하는 라이브러리에만 적용 가능
- 사전 빌드 단계에서 템플릿 을 실행하려면 프로젝트를 구성하고 빌드 서버가 선택하지 않은 경우 빌드 서버가 필요합니다 . ( V가없는 T4 참조 ).
답변
어셈블리 PE 헤더의 바이트에서 빌드 날짜 / 버전 정보를 가져 오는 기술과 관련하여 Microsoft는 Visual Studio 15.4부터 기본 빌드 매개 변수를 변경했습니다. 새로운 기본값에는 결정적 컴파일이 포함되어있어 유효한 타임 스탬프와 자동으로 증가 된 버전 번호를 과거의 것으로 만듭니다. 타임 스탬프 필드는 여전히 존재하지만 무언가 또는 다른 것의 해시이지만 빌드 시간의 표시가 아닌 영구적 인 값으로 채워집니다.
결정 론적 컴파일보다 유용한 타임 스탬프를 우선시하는 사람들에게는 새로운 기본값을 무시하는 방법이 있습니다. 관심있는 어셈블리의 .csproj 파일에 다음과 같이 태그를 포함 할 수 있습니다.
<PropertyGroup>
...
<Deterministic>false</Deterministic>
</PropertyGroup>
업데이트 : 다른 답변에 설명 된 T4 텍스트 템플릿 솔루션을 추천합니다. 결정적 컴파일의 이점을 잃지 않고 문제를 깨끗하게 해결하는 데 사용했습니다. 주의 할 점은 Visual Studio는 빌드 시간이 아닌 .tt 파일을 저장할 때 T4 컴파일러 만 실행한다는 것입니다. 소스 컨트롤에서 .cs 결과를 제외하고 (생성 할 것으로 예상되므로) 다른 개발자가 코드를 체크 아웃하면이 작업이 어색 할 수 있습니다. 다시 저장하지 않으면 .cs 파일이 없습니다. 너겟에는 패키지가 있습니다 (AutoT4라고 생각합니다) .T4 컴파일을 모든 빌드의 일부로 만듭니다. 프로덕션 배포 중에 아직 이것에 대한 솔루션에 직면하지 않았지만 비슷한 것을 올바르게 할 것으로 기대합니다.
답변
나는 단지 C # 초보자이므로 아마도 내 대답 소리가 어리석은 일입니다-실행 파일이 마지막으로 작성된 날짜부터 빌드 날짜를 표시합니다.
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이지만 창 탐색기의 날짜는 2012-05-23을 보여줍니다. 이 불일치를 검색 한 후 파일이 2012 년 5 월 23 일 (Windows 탐색기로 표시)에 생성되었지만 2012 년 5 월 29 일 (현재 File.GetCreationTime 명령으로 표시)의 현재 폴더로 복사 된 것으로 확인되었습니다. File.GetLastWriteTime 명령을 사용하고 안전 측면에 있습니다.
잘렉
