Search code examples
delphidelphi-7

How can I read details of file?


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.


Solution

  • 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)