15

How can I read details of an exe file like File Version, Product Version and anything else stored in Details tab in Properties window of that file? Thanks.

Fabrizio
  • 7,603
  • 6
  • 44
  • 104
Armin Taghavizad
  • 1,625
  • 7
  • 35
  • 57

1 Answers1

34

This has been described at About:

Basically, you just use the GetFileVersionInfo function to obtain the data and then VerQueryValue function to read it.

Because these API functions are a bit 'hard' to use, I have written a simple example:

type
  TEXEVersionData = record
    CompanyName,
    FileDescription,
    FileVersion,
    InternalName,
    LegalCopyright,
    LegalTrademarks,
    OriginalFileName,
    ProductName,
    ProductVersion,
    Comments,
    PrivateBuild,
    SpecialBuild: string;
  end;

function GetEXEVersionData(const FileName: string): TEXEVersionData;
type
  PLandCodepage = ^TLandCodepage;
  TLandCodepage = record
    wLanguage,
    wCodePage: word;
  end;
var
  dummy,
  len: cardinal;
  buf, pntr: pointer;
  lang: string;
begin
  len := GetFileVersionInfoSize(PChar(FileName), dummy);
  if len = 0 then
    RaiseLastOSError;
  GetMem(buf, len);
  try
    if not GetFileVersionInfo(PChar(FileName), 0, len, buf) then
      RaiseLastOSError;

    if not VerQueryValue(buf, '\VarFileInfo\Translation\', pntr, len) then
      RaiseLastOSError;

    lang := Format('%.4x%.4x', [PLandCodepage(pntr)^.wLanguage, PLandCodepage(pntr)^.wCodePage]);

    if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\CompanyName'), pntr, len){ and (@len <> nil)} then
      result.CompanyName := PChar(pntr);
    if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\FileDescription'), pntr, len){ and (@len <> nil)} then
      result.FileDescription := PChar(pntr);
    if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\FileVersion'), pntr, len){ and (@len <> nil)} then
      result.FileVersion := PChar(pntr);
    if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\InternalName'), pntr, len){ and (@len <> nil)} then
      result.InternalName := PChar(pntr);
    if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\LegalCopyright'), pntr, len){ and (@len <> nil)} then
      result.LegalCopyright := PChar(pntr);
    if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\LegalTrademarks'), pntr, len){ and (@len <> nil)} then
      result.LegalTrademarks := PChar(pntr);
    if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\OriginalFileName'), pntr, len){ and (@len <> nil)} then
      result.OriginalFileName := PChar(pntr);
    if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\ProductName'), pntr, len){ and (@len <> nil)} then
      result.ProductName := PChar(pntr);
    if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\ProductVersion'), pntr, len){ and (@len <> nil)} then
      result.ProductVersion := PChar(pntr);
    if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\Comments'), pntr, len){ and (@len <> nil)} then
      result.Comments := PChar(pntr);
    if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\PrivateBuild'), pntr, len){ and (@len <> nil)} then
      result.PrivateBuild := PChar(pntr);
    if VerQueryValue(buf, PChar('\StringFileInfo\' + lang + '\SpecialBuild'), pntr, len){ and (@len <> nil)} then
      result.SpecialBuild := PChar(pntr);
  finally
    FreeMem(buf);
  end;
end;

Try it. But beware -- currently, this only works for en-us EXEs! It doesn't work for most of the EXEs on my Swedish machine, for instance. It is late now; tomorrow I will extend this to work with any EXE language, if only I get some time left. [The About.com code has the same problem, but they don't even pretend it is a problem!]

Update: The code now works with any EXE language.

Sample usage on Explorer.exe (Swedish)
(Swedish)

dummzeuch
  • 10,975
  • 4
  • 51
  • 158
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • Very useful. my first search source was ABOUT, but i could not find it, i wonder why!!!. Really Thank you – Armin Taghavizad Apr 04 '11 at 14:36
  • I get this error while compiling: "Types of actual and formal var parameters must be identical" Wheres the problem? I did not make any change to described functions! – Armin Taghavizad Apr 04 '11 at 18:54
  • @Armin: It would help if you told us what line the error occurrs at. – Andreas Rejbrand Apr 04 '11 at 19:09
  • Sure! The line: "n := GetFileVersionInfoSize(PChar(S),n) ;" | The 6th line in "VersionInformation Function". It has the same problem at this line: "...InfoStr[j]),Pointer(Value),Len) Then..." | The 14th line of "VersionInformation function". Also this error "Incompatible types: 'String' and 'Array'" in this code "...(StringPad(labelStr,' ',20,True)+' = '+Value) ;" | 20th line of "Version Information Function". im using Delphi-7 as shown in question tags. – Armin Taghavizad Apr 04 '11 at 19:24
  • i also checked these links, but didnt help, wrong and empty results!! 1)[http://www.delphidabbler.com/articles?article=20](http://www.delphidabbler.com/articles?article=20) 2)[http://www.swissdelphicenter.ch/torry/showcode.php?id=1047](http://www.swissdelphicenter.ch/torry/showcode.php?id=1047) – Armin Taghavizad Apr 04 '11 at 19:37
  • 1
    @Armin: Skip the about.com code! I just wrote a simple example myself. – Andreas Rejbrand Apr 04 '11 at 22:35
  • Hey, it really worked! Your code worked perfect. Really thank you. i searched long time but i didnt find anything.. – Armin Taghavizad Apr 04 '11 at 22:53
  • @Robrok: Project/Options.../'Version Info'. – Andreas Rejbrand May 10 '11 at 13:33
  • Excellent thank you!! You overcame the long standing problem of which locale ID the resource information is stored in. – Reversed Engineer May 05 '16 at 11:19
  • What's the thing with the commented out `@len <> nil`? – Uli Gerhardt Sep 13 '18 at 10:06
  • Very helpful! - I just added a Trim() to the results though, as you get a lot of whitespace. – T.S Jan 29 '20 at 09:17
  • @AndreasRejbrand this won't catch _anything_, only keys whose names you yet know already. Parsing the VS_VERSION_INFO data in `buf` oneself is challenging, but then you can read any key+value (and multiple language blocks, too). – AmigoJack Feb 22 '21 at 00:51