Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Erstellungsdatum von BPL auslesen (https://www.delphipraxis.net/161523-erstellungsdatum-von-bpl-auslesen.html)

himitsu 7. Jul 2011 11:29


Erstellungsdatum von BPL auslesen
 
Tachchen,

das Compilierungsdatum von EXE und DLL kann man ja leicht auslesen,
aber bei BPLs erhalte ich kein Ergebnis. :cry:
Datum und Uhrzeit der Kompilierung (Compile Date Time)Datum und Uhrzeit der Kompilierung (Compile Date Time)

Dabei sind doch BPLs auch "nur" DLLs.


Hat dafür jemand eine Lösung?


[edit]
Arg, hab ganz vergessen, daß hier die BPLs wo anders liegen.
Jetzt muß ich nur noch wieder rausfinden, wie man diese Dateien dann findet, damit CreateFile diese öffnen kann.

himitsu 7. Jul 2011 13:01

AW: Erstellungsdatum von BPL auslesen
 
So, hier nun noch der Code, mit einer kleinen Änderung, welche notfalls die Datei sucht (gut für DLLs und BPLs), wenn man in seinem Programm deratige Infos anzeigen/prüfen möchte.

@CodLibMods: könnt ihr ja gerne mit dort in der CodeLib anhängen, wenn ihr wollt :angle:
http://www.delphipraxis.net/11694-da...date-time.html

Funktioniert mindestens seit Delphi 4 bis Delphi XE (beim 64 Bit XE2 müssen wir dann mal sehn, wie/ob es dort läuft)

Delphi-Quellcode:
// Nico Bendlin and himitsu
function GetImageLinkTimeStamp(Filename: String): TDateTime;
const
  INVALID_SET_FILE_POINTER = DWORD(-1);
  BorlandMagicTimeStamp = $2A425E19; // Delphi 4-6 (and above?)  // jupp, mindestens bis XE, wobei es hier nicht mehr nötig ist, da seit D2009/D2010 endlich das Datum im NTHeader einkompiliert wird.
  FileTime1970: TFileTime = (dwLowDateTime:$D53E8000; dwHighDateTime:$019DB1DE);
type
  PImageSectionHeaders = ^TImageSectionHeaders;
  TImageSectionHeaders = array [Word] of TImageSectionHeader;
type
  PImageResourceDirectory = ^TImageResourceDirectory;
  TImageResourceDirectory = packed record
    Characteristics: DWORD;
    TimeDateStamp: DWORD;
    MajorVersion: Word;
    MinorVersion: Word;
    NumberOfNamedEntries: Word;
    NumberOfIdEntries: Word;
  end;
var
  FileHandle: THandle;
  BytesRead: DWORD;
  ImageDosHeader: TImageDosHeader;
  ImageNtHeaders: TImageNtHeaders;
  SectionHeaders: PImageSectionHeaders;
  Section: Word;
  ResDirRVA: DWORD;
  ResDirSize: DWORD;
  ResDirRaw: DWORD;
  ResDirTable: TImageResourceDirectory;
  FileTime: TFileTime;
  SearchFilename: String;
  Schrott: PChar;
begin
  Result := UnixTimeToDateTime(0);
  if GetModuleHandle(PChar(Filename)) <> 0 then begin
    SearchFilename := GetModuleName(GetModuleHandle(PChar(Filename)));
    if (SearchFilename <> '') and FileExists(SearchFilename) then Filename := SearchFilename;
  end;
  if ExtractFilePath(Filename) = '' then begin
    SetLength(SearchFilename, MAX_PATH-1);
    SetLength(SearchFilename, SearchPath(Pointer(ExtractFileDir(Filename)), PChar(ExtractFileName(Filename)), nil, MAX_PATH, PChar(SearchFilename), Schrott));
    if SearchFilename <> '' then Filename := SearchFilename;
  end;
  FileHandle := CreateFile(PChar(Filename), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
  if FileHandle <> INVALID_HANDLE_VALUE then
    try
      // Read MS-DOS header to get the offset of the PE32 header (not required on WinNT based systems - but mostly available)
      if not ReadFile(FileHandle, ImageDosHeader, SizeOf(TImageDosHeader), BytesRead, nil)
          or (BytesRead <> SizeOf(TImageDosHeader)) or (ImageDosHeader.e_magic <> IMAGE_DOS_SIGNATURE) then
        ImageDosHeader._lfanew := 0;
      // Read PE32 header (including optional header)
      if (SetFilePointer(FileHandle, ImageDosHeader._lfanew, nil, FILE_BEGIN) = INVALID_SET_FILE_POINTER)
          or not (ReadFile(FileHandle, ImageNtHeaders, SizeOf(TImageNtHeaders), BytesRead, nil)
          and (BytesRead = SizeOf(TImageNtHeaders))) then
        Exit;
      // Validate PE32 image header
      if ImageNtHeaders.Signature <> IMAGE_NT_SIGNATURE then
        Exit;
      // Seconds since 1970 (UTC)
      Result := UnixTimeToDateTime(ImageNtHeaders.FileHeader.TimeDateStamp);
      // Check for Borland's magic value for the link time stamp (we take the time stamp from the resource directory table)
      if ImageNtHeaders.FileHeader.TimeDateStamp = BorlandMagicTimeStamp then
        with ImageNtHeaders, FileHeader, OptionalHeader do begin
          // Validate Optional header
          if (SizeOfOptionalHeader < IMAGE_SIZEOF_NT_OPTIONAL_HEADER) or (Magic <> IMAGE_NT_OPTIONAL_HDR_MAGIC) then
            Exit;
          // Read section headers
          SectionHeaders := GetMemory(NumberOfSections * SizeOf(TImageSectionHeader));
          if Assigned(SectionHeaders) then
            try
              if (SetFilePointer(FileHandle, SizeOfOptionalHeader - IMAGE_SIZEOF_NT_OPTIONAL_HEADER, nil, FILE_CURRENT) = INVALID_SET_FILE_POINTER)
                  or not ReadFile(FileHandle, SectionHeaders^, NumberOfSections * SizeOf(TImageSectionHeader), BytesRead, nil)
                  and (BytesRead = NumberOfSections * SizeOf(TImageSectionHeader)) then
                Exit;
              // Get RVA and size of the resource directory
              with DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] do begin
                ResDirRVA := VirtualAddress;
                ResDirSize := Size;
              end;
              // Search for section which contains the resource directory
              ResDirRaw := 0;
              for Section := 0 to NumberOfSections - 1 do
              with SectionHeaders[Section] do
                if (VirtualAddress <= ResDirRVA) and (VirtualAddress + SizeOfRawData >= ResDirRVA + ResDirSize) then begin
                  ResDirRaw := PointerToRawData - (VirtualAddress - ResDirRVA);
                  Break;
                end;
              // Resource directory table found?
              if ResDirRaw = 0 then
                Exit;
              // Read resource directory table
              if (SetFilePointer(FileHandle, ResDirRaw, nil, FILE_BEGIN) = INVALID_SET_FILE_POINTER)
                  or not (ReadFile(FileHandle, ResDirTable, SizeOf(TImageResourceDirectory), BytesRead, nil)
                  and (BytesRead = SizeOf(TImageResourceDirectory))) then
                Exit;
              // Convert from DosDateTime to SecondsSince1970
              if DosDateTimeToFileTime(HiWord(ResDirTable.TimeDateStamp), LoWord(ResDirTable.TimeDateStamp), FileTime) then
                // FIXME: Borland's linker uses the local system time of the user who linked the executable image file. (is that information anywhere?)
                Result := UnixTimeToDateTime((ULARGE_INTEGER(FileTime).QuadPart - ULARGE_INTEGER(FileTime1970).QuadPart) div 10000000);
            finally
              FreeMemory(SectionHeaders);
            end;
        end;
    finally
      CloseHandle(FileHandle);
    end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:28 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz