Application version: alternative to GetFileVersionInfo
2005-06-08 22:05 i93 [permalink]
GetFileVersionInfo can have trouble with your executable being locked. Normally it doesn't, but still, if you know when starting an application, all resources in the exe-file are loaded into memory, it makes no sense to re-read the exe-file to get to the version resource data.
There is a resource type RT_VERSION. A ready-made standard-Delphi object TResourceStream
provides access to the version data. VerQueryValue
can read this data for you. Strangely enough you need to copy the data for it to get accessable, I copy it to a TMemoryStream here:
uses Windows,Classes,SysUtils;
var
verblock:PVSFIXEDFILEINFO;
versionMS,versionLS:cardinal;
verlen:cardinal;
rs:TResourceStream;
m:TMemoryStream;
p:pointer;
s:cardinal;
begin
m:=TMemoryStream.Create;
rs:=TResourceStream.CreateFromID(HInstance,1,RT_VERSION);
m.CopyFrom(rs,rs.Size);
rs.Free;
m.Position:=0;
if VerQueryValue(m.Memory,'\',pointer(verblock),verlen) then
begin
VersionMS:=verblock.dwFileVersionMS;
VersionLS:=verblock.dwFileVersionLS;
AppVersionString:=Application.Title+' '+
IntToStr(versionMS shr 16)+'.'+
IntToStr(versionMS and $FFFF)+'.'+
IntToStr(VersionLS shr 16)+'.'+
IntToStr(VersionLS and $FFFF);
end;
if VerQueryValue(m.Memory,PChar('\\StringFileInfo\\'+IntToHex(GetThreadLocale,4)+IntToHex(GetACP,4)+'\\FileDescription'),p,s) or
VerQueryValue(m.Memory,'\\StringFileInfo\\081304E4\\FileDescription',p,s) or //nl-be?
VerQueryValue(m.Memory,'\\StringFileInfo\\040904E4\\FileDescription',p,s) then //en-us?
AppVersionString:=PChar(p)+' '+AppVersionString;
m.Free;
end;
The text info in the version resource data is stored per locale-id/codepage-id combination (I haven't seen any version data blocks with more than one of this combinations, but then again, I haven't seen that much binary data of versionresourcedatablocks) so there's the option of picking up the currently valid LCID, or have some default (nl-be in my case, $0813, and internationally default $0409 also). The Delphi Project Options dialog, version tab, has a locale selection, so if you're sure about which one you're using there, you might just use that one in a single VerQueryValue in the last if statement.