Le chemin
Comme l'a souligné @ c00000fd dans les commentaires . Microsoft change cela. Et bien que beaucoup de gens n'utilisent pas la dernière version de leur compilateur, je soupçonne que ce changement rend cette approche incontestablement mauvaise. Et bien que ce soit un exercice amusant, je recommanderais aux gens d'incorporer simplement une date de construction dans leur binaire par tout autre moyen nécessaire s'il est important de suivre la date de construction du binaire lui-même.
Cela peut être fait avec une génération de code triviale qui est probablement déjà la première étape de votre script de construction. Cela, et le fait que les outils ALM / Build / DevOps aident beaucoup à cela et devraient être préférés à toute autre chose.
Je laisse le reste de cette réponse ici à des fins historiques uniquement.
La nouvelle façon
J'ai changé d'avis à ce sujet et j'utilise actuellement cette astuce pour obtenir la bonne date de construction.
#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
L'ancienne façon
Eh bien, comment générer des numéros de build? Visual Studio (ou le compilateur C #) fournit en fait des numéros de construction et de révision automatiques si vous changez l'attribut AssemblyVersion par exemple1.0.*
Ce qui se passera, c'est que la génération sera égale au nombre de jours depuis le 1er janvier 2000, heure locale, et que la révision soit égale au nombre de secondes depuis minuit, heure locale, divisé par 2.
voir les numéros de contenu communautaire, de génération automatique et de révision
par exemple 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)