方式
正如@c00000fd 在comments 中指出的那样。微软正在改变这一点。虽然许多人不使用最新版本的编译器,但我怀疑这种变化使这种方法无疑是糟糕的。虽然这是一个有趣的练习,但如果跟踪二进制文件本身的构建日期很重要,我建议人们通过任何其他必要的方式将构建日期简单地嵌入到他们的二进制文件中。
这可以通过一些简单的代码生成来完成,这可能已经是构建脚本的第一步。这一点,以及 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。
查看社区内容,Automatic Build and Revision numbers
例如AssemblyInfo.cs
[assembly: AssemblyVersion("1.0.*")] // important: use wildcard for build and revision numbers!
示例代码.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)