Как получить доступ к дате сборки dll в C # - PullRequest
3 голосов
/ 26 ноября 2010

Есть ли какой-нибудь способ получить доступ к дате и времени сборки dll из C #?

В промежутке между формальными выпусками dll я хотел бы иметь возможность каким-то образом хранить время / дату сборки DLLтак что я могу проверить, является ли текущая сборка ожидаемой.Я работаю над версиями надстройки Debug и Release, и я легко могу забыть, какую из них я использую в настоящее время, особенно на нескольких машинах для разработки, тестирования и подготовки к работе.Я хочу иметь возможность перейти к моему окну «О программе» и отобразить его там.

TIA, Paolo

Ответы [ 4 ]

3 голосов
/ 27 ноября 2010

Вы можете использовать TimeDateStamp поле IMAGE_FILE_HEADER , которое представляет дату и время создания изображения компоновщиком Это значение полезно, поскольку оно не зависит от даты / времени файла в файловой системе.

Соответствующий код .NET 4.0 может быть примерно следующим:

using System;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
using System.IO;

namespace GetPeLinkTime {
    class Program {
        static void Main (string[] args) {
            if (args.Length != 1) {
                Console.WriteLine ("Usage:" + Environment.NewLine + "    GetPeLinkTime ExePathToExamine");
                return;
            }
            string filePath = args[0];

            FileStream file = File.OpenRead (filePath);
            using (var mmf = MemoryMappedFile.CreateFromFile (file, null, 
                                                              file.Length,
                                                              MemoryMappedFileAccess.Read,
                                                              null, HandleInheritability.None, false)) {
                NativeMethods.IMAGE_DOS_HEADER dosHeader = new NativeMethods.IMAGE_DOS_HEADER ();
                using (var accessor = mmf.CreateViewAccessor (0,
                                                              Marshal.SizeOf (dosHeader),
                                                              MemoryMappedFileAccess.Read)) {
                    accessor.Read<NativeMethods.IMAGE_DOS_HEADER>(0, out dosHeader);
                    if (dosHeader.e_magic != NativeMethods.IMAGE_DOS_SIGNATURE) {
                        Console.WriteLine ("The input file is not an Executable file.");
                        return;
                    }
                }
                int signature = 0;
                NativeMethods.IMAGE_FILE_HEADER imageFileHeader = new NativeMethods.IMAGE_FILE_HEADER();
                using (var accessor = mmf.CreateViewAccessor (dosHeader.e_lfanew,
                                                              Marshal.SizeOf (signature) + Marshal.SizeOf (imageFileHeader),
                                                              MemoryMappedFileAccess.Read)) {
                    signature = accessor.ReadInt32 (0);
                    if (signature != NativeMethods.IMAGE_NT_SIGNATURE) {
                        Console.WriteLine ("The input file is not a Program Executable file.");
                        return;
                    }
                    accessor.Read<NativeMethods.IMAGE_FILE_HEADER> (Marshal.SizeOf (signature), out imageFileHeader);
                }
                // convert a Unix timestamp to DateTime
                DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
                TimeSpan localOffset = TimeZone.CurrentTimeZone.GetUtcOffset (origin);
                DateTime originUTC = origin.AddHours(localOffset.Hours);
                DateTime linkTime = originUTC.AddSeconds ((double)imageFileHeader.TimeDateStamp);
                Console.WriteLine ("Link time of the file '{0}' is: {1}", filePath, linkTime);
            }
        }
    }
    internal static class NativeMethods {
        internal const int IMAGE_DOS_SIGNATURE = 0x5A4D;    // MZ
        internal const int IMAGE_NT_SIGNATURE = 0x00004550; // PE00

        [StructLayout (LayoutKind.Sequential)]
        internal struct IMAGE_DOS_HEADER {  // DOS .EXE header
            internal short e_magic;         // Magic number
            internal short e_cblp;          // Bytes on last page of file
            internal short e_cp;            // Pages in file
            internal short e_crlc;          // Relocations
            internal short e_cparhdr;       // Size of header in paragraphs
            internal short e_minalloc;      // Minimum extra paragraphs needed
            internal short e_maxalloc;      // Maximum extra paragraphs needed
            internal short e_ss;            // Initial (relative) SS value
            internal short e_sp;            // Initial SP value
            internal short e_csum;          // Checksum
            internal short e_ip;            // Initial IP value
            internal short e_cs;            // Initial (relative) CS value
            internal short e_lfarlc;        // File address of relocation table
            internal short e_ovno;          // Overlay number
            internal short e_res1;          // Reserved words
            internal short e_res2;          // Reserved words
            internal short e_res3;          // Reserved words
            internal short e_res4;          // Reserved words
            internal short e_oemid;         // OEM identifier (for e_oeminfo)
            internal short e_oeminfo;       // OEM information; e_oemid specific
            internal short e_res20;         // Reserved words
            internal short e_res21;         // Reserved words
            internal short e_res22;         // Reserved words
            internal short e_res23;         // Reserved words
            internal short e_res24;         // Reserved words
            internal short e_res25;         // Reserved words
            internal short e_res26;         // Reserved words
            internal short e_res27;         // Reserved words
            internal short e_res28;         // Reserved words
            internal short e_res29;         // Reserved words
            internal int e_lfanew;          // File address of new exe header
        }
        [StructLayout (LayoutKind.Sequential)]
        internal struct IMAGE_FILE_HEADER {
            internal short Machine;
            internal short NumberOfSections;
            internal int TimeDateStamp;
            internal int PointerToSymbolTable;
            internal int NumberOfSymbols;
            internal short SizeOfOptionalHeader;
            internal short Characteristics;
        }
        //struct _IMAGE_NT_HEADERS {
        //    DWORD Signature;
        //    IMAGE_FILE_HEADER FileHeader;
        //    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
        //}
        //struct _IMAGE_NT_HEADERS64 {
        //    DWORD Signature;
        //    IMAGE_FILE_HEADER FileHeader;
        //    IMAGE_OPTIONAL_HEADER64 OptionalHeader;
        //}
    }
}
2 голосов
/ 26 ноября 2010

Вы можете использовать класс FileInfo.

FileInfo file = new FileInfo(pathToDll);
DateTime dllCreateTime = file.CreationTime;
1 голос
/ 26 ноября 2010

По какой причине вы не хотите использовать последний бит номера версии сборки?Вы можете получить к нему доступ через свойство Version.Revision.Это довольно простой способ идентифицировать сборку, IMO.

0 голосов
/ 26 ноября 2010

Нечто подобное здесь , используя описание информации о сборке

...