![]() |
Compilierdatum
Hallo,
was ich schon lange suche und noch nie gefunden habe: Legt der Delphi-Compiler irgendwo in der Exe das Datum des Compilierens ab? Das Datum der Exe nützt mir dabei nichts, das kann man ändern. Automatisch hineincompilieren geht auch, mir wäre aber eine 'eingebaute' Lösung lieber. Danke und viele Grüße! |
Re: Compilierdatum
Hallo Delphianer,
für das Datum fällt mir ad hoc keine Lösung ein, aber vielleicht hilf Dir die Suche nach ![]() |
Re: Compilierdatum
Danke,
aber das ist es nicht. Ich suche etwas, was Delphi automatisch einträgt. |
Re: Compilierdatum
Delphi ist in der Lage, die Versionsnummer bei jedem Build automatisch zu inkrementieren.
Oder muss es unbedingt das Datum sein? |
Re: Compilierdatum
Ja, ich suche das Compilierdatum, von Delphi höchstselbst eingetragen. Aus irgendeinem Grund scheinen das die Delphi-Entwickler aber nicht vorgesehen zu haben, oder?
|
Re: Compilierdatum
Normalerweise sollte das Compilierungsdatum und die EXE Prüfsumme im PE Fileheader der EXE stehen. Aber, was ist schon normal ? denn der Delphi Compiler legt da seinen eigenen Magic-Mist rein. Die CRC berechnet er garnicht.
Nungut, es gibt aber einen Weg. Der Linker von Delphi erzeugt die EXE aus den Code-/Daten- und Resourcesegementen. Jedesmal wenn du compilierst linkt er also die Resourcen in die EXE neu rein. Es sind immer Resourcen vorhanden. Eine Resource hat ein Erstellungsdatum und dieses ist identisch mit der Compilierungszeit. D.h. für dich das du nur durch die Resourcen des Modules iterieren musst bis du die erste findest. Aus dieser Resource liest du dann das Datum aus. Gruß Hagen |
Re: Compilierdatum
Code von Nico:
Delphi-Quellcode:
Rückgabewert ist ein Unix TimeStamp.
function GetImageLinkTimeStamp(const FileName: string): DWORD;
const INVALID_SET_FILE_POINTER = DWORD(-1); BorlandMagicTimeStamp = $2A425E19; // Delphi 4-6 (and above?) 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; begin Result := 0; // Open file for read access 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 begin ImageDosHeader._lfanew := 0; end; // Read PE32 header (including optional header if (SetFilePointer(FileHandle, ImageDosHeader._lfanew, nil, FILE_BEGIN) = INVALID_SET_FILE_POINTER) then begin Exit; end; if not(ReadFile(FileHandle, ImageNtHeaders, SizeOf(TImageNtHeaders), BytesRead, nil) and (BytesRead = SizeOf(TImageNtHeaders))) then begin Exit; end; // Validate PE32 image header if (ImageNtHeaders.Signature <> IMAGE_NT_SIGNATURE) then begin Exit; end; // Seconds since 1970 (UTC) Result := 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 begin Exit; end; // 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) then begin Exit; end; if not(ReadFile(FileHandle, SectionHeaders^, NumberOfSections * SizeOf(TImageSectionHeader), BytesRead, nil) and (BytesRead = NumberOfSections * SizeOf(TImageSectionHeader))) then begin Exit; end; // 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 begin Exit; end; // Read resource directory table if (SetFilePointer(FileHandle, ResDirRaw, nil, FILE_BEGIN) = INVALID_SET_FILE_POINTER) then begin Exit; end; if not(ReadFile(FileHandle, ResDirTable, SizeOf(TImageResourceDirectory), BytesRead, nil) and (BytesRead = SizeOf(TImageResourceDirectory))) then begin Exit; end; // Convert from DosDateTime to SecondsSince1970 if DosDateTimeToFileTime(HiWord(ResDirTable.TimeDateStamp), LoWord(ResDirTable.TimeDateStamp), FileTime) then begin // FIXME: Borland's linker uses the local system time // of the user who linked the executable image file. // (is that information anywhere?) Result := (ULARGE_INTEGER(FileTime).QuadPart - ULARGE_INTEGER(FileTime1970).QuadPart) div 10000000; end; finally FreeMemory(SectionHeaders); end; end; finally CloseHandle(FileHandle); end; end; |
Re: Compilierdatum
Hallo Luckie,
bitte in die CodeLib stellen! p.s. Das ist ja ein richtiger Schatz :thuimb: |
Re: Compilierdatum
Hallo Luckie und negaH,
das klingt beides gut. Ich werde es ausprobieren, danke! Viele Grüße! |
Re: Compilierdatum
Delphi-Quellcode:
Hab ich ausprobiert. Bekomme aber diese Fehlermeldung:
Label1.Caption:= DateTimeToStr(UnixToDateTime(GetImageLinkTimeStamp(Application.ExeName)));
"Undeclared Identifier UnixToDateTime" Was mach ich falsch, oder was hab ich vergessen? Würde gerne Datum und Zeit in die Caption der Form1 einbringen. So wie im Programm VirtualDub... Ich denke ich hab ne variable vergessen... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:59 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