yoy.be "Why-o-Why"

Application version: alternative to GetFileVersionInfo

2005-06-08 22:05  i93  delphi  [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.

twitter reddit linkedin facebook