Displaying the build date

前端 未结 25 2474
感动是毒
感动是毒 2020-11-22 11:36

I currently have an app displaying the build number in its title window. That\'s well and good except it means nothing to most of the users, who want to know if they have t

25条回答
  •  生来不讨喜
    2020-11-22 12:14

    The way

    As pointed out by @c00000fd in the comments. Microsoft is changing this. And while many people don't use the latest version of their compiler I suspect this change makes this approach unquestionably bad. And while it's a fun exercise I would recommend people to simply embed a build date into their binary through any other means necessary if it's important to track the build date of the binary itself.

    This can be done with some trivial code generation which probably is the first step in your build script already. That, and the fact that ALM/Build/DevOps tools help a lot with this and should be preferred to anything else.

    I leave the rest of this answer here for historical purposes only.

    The new way

    I changed my mind about this, and currently use this trick to get the correct build date.

    #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
    

    The old way

    Well, how do you generate build numbers? Visual Studio (or the C# compiler) actually provides automatic build and revision numbers if you change the AssemblyVersion attribute to e.g. 1.0.*

    What will happen is that is that the build will be equal to the number of days since January 1, 2000 local time, and for revision to be equal to the number of seconds since midnight local time, divided by 2.

    see Community Content, Automatic Build and Revision numbers

    e.g. 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)
    

提交回复
热议问题