Шлях
Як вказував @ 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 на напр.1.0.*
Що відбудеться, так це те, що збірка буде дорівнює кількості днів з 1 січня 2000 року за місцевим часом, а для доопрацювання дорівнює кількості секунд з часу півночі за місцевим часом, поділеною на 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)