![]() |
Erstellungsdatum von BPL auslesen
Tachchen,
das Compilierungsdatum von EXE und DLL kann man ja leicht auslesen, aber bei BPLs erhalte ich kein Ergebnis. :cry: ![]() 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. |
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: ![]() 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 04:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz