function VSFixedFileInfoToString(
const VS: TVSFixedFileInfo;
const AsInt64: PInt64):
string;
begin
with VS
do
begin
Result := Format('
%d.%d.%d.%d', [HiWord(dwFileVersionMS),
// Major
LoWord(dwFileVersionMS),
// Minor
HiWord(dwFileVersionLS),
// Release
LoWord(dwFileVersionLS)]);
// Build
if Assigned(AsInt64)
then
AsInt64^ := Int64(dwFileVersionMS)
shl 32
or dwFileVersionLS;
end;
end;
function GetFileVersionFromResource(
const ResourceName:
string; AsInt64: PInt64 =
nil):
string;
var
RS: TResourceStream;
begin
RS := TResourceStream.Create(HInstance, ResourceName, RT_RCDATA);
try
Result := GetFileVersionFromStream(RS, AsInt64);
finally
RS.Free;
end;
end;
function GetFileVersionFromStream(Stream: TStream; AsInt64: PInt64 =
nil):
string;
const
Offset = 2048;
VS_VERSION_INFO: WideString = '
VS_VERSION_INFO';
Signature = $FEEF04BD;
var
WS: WideString;
PVerValue: PVSFixedFileInfo;
i: Integer;
begin
Result := '
';
if Assigned(AsInt64)
then AsInt64^ := 0;
// Die Versionsinfo-Daten befinden sich ziemlich am Ende einer EXE/DLL
// gehe also zum Ende des Streams minus Offset (2 KB sollten genügen)
Stream.Seek(-Offset, soFromEnd);
// Daten in WideString kopieren
i := Stream.Size - Stream.Position;
SetLength(WS, i
div 2 + 1);
Stream.ReadBuffer(WS[Low(WS)], i);
// Position der ID 'VS_VERSION_INFO' ermitteln, Signatur prüfen, Version auslesen
i := Pos(VS_VERSION_INFO, WS);
PVerValue := PVSFixedFileInfo(@WS[i + Length(VS_VERSION_INFO) + 2]);
if (i >= Low(WS))
and (PVerValue^.dwSignature = Signature)
then
Result := VSFixedFileInfoToString(PVerValue^, AsInt64);
end;