0
votes

In the Project Options, there are some informations that can be set for the compiled file, like:

  • CompanyName
  • FileDescription
  • FileVersion
  • InternalName
  • LegalCopyright
  • LegalTrademarks
  • OriginalFilename
  • ProductName
  • ProductVersion
  • Comments

I know how to extract the file version from the compiled file (exe/bpl) at runtime, but I don't know how to extract these extra informations.

In particular, I would like to get the ProductVersion value

Project Options window displaying the Version Info settings

1
Did you see this question ? : stackoverflow.com/questions/1717844/…Charles-Henri
@Charles-Henri: It's a different question but I've noticed that Jiri Krivanek's answer fit also for my questionFabrizio
There can be up to two product version records stored in VERSIONINFO. The first one is stored as number (2 DWORDs) in TVSFixedFileInfo and the second one is stored as string in StringFileInfo under ProductVersion key. The latter can is not limited to numbers and can contain other information like BETA or RC1.Peter Wolf
@PeterWolf: I'm looking for the one stored in StringFileInfo for the Locale ID $0409 (I suppose...) but where can I find some information about these two kind of file informations?Fabrizio
See official MS documentation for VERSIONINFO resource that I already posted. See also sub-category StringFileInfo block in the navigation pane of the documentation.Peter Wolf

1 Answers

1
votes

Here after is the code to get the ProductVersion out of the executable file (Or any file given his file name):

type
    TLangAndCodePage = record
        wLanguage : WORD;
        wCodePage : WORD;
    end;
    PLangAndCodePage = ^TLangAndCodePage;

    procedure TForm1.Button1Click(Sender: TObject);
    var
        InfoSize        : Integer;
        ValueSize       : DWORD;
        Dummy           : DWORD;
        VerInfo         : Pointer;
        LangAndCodePage : PLangAndCodePage;
        Ptr             : PLangAndCodePage;
        TranslateBytes  : UINT;
        I               : Integer;
        SubBlock        : String;
        SubBlockBuffer  : PChar;
    begin
        InfoSize := GetFileVersionInfoSize(PChar(Application.ExeName), Dummy);
        if InfoSize <> 0 then begin
            GetMem(VerInfo, InfoSize);
            try
                if GetFileVersionInfo(PChar(Application.ExeName), 0,
                                      InfoSize, VerInfo) then begin
    
                    VerQueryValue(VerInfo,
                                  '\VarFileInfo\Translation',
                                  Pointer(LangAndCodePage),
                                  TranslateBytes);
    
                    Ptr := LangAndCodePage;
                    for I := 0 to (TranslateBytes div SizeOf(TLangAndCodePage)) - 1 do begin
                        SubBlock := Format('\StringFileInfo\%04.4X%04.4X\ProductVersion',
                                           [Ptr.wLanguage, Ptr.wCodePage]);
                        Memo1.Lines.Add(SubBlock);
    
                        VerQueryValue(VerInfo,
                                      PChar(SubBlock),
                                      Pointer(SubBlockBuffer),
                                      ValueSize);
                        Memo1.Lines.Add('  ProductVersion="' + SubBlockBuffer + '"');
    
                        Inc(Ptr);
                    end;
                end;
            finally
                FreeMem(VerInfo, InfoSize);
            end;
        end;
    end;

The code first by querying the languages available and then iterate thru all languages available.

SubBlock is actually a kind of path for the value to query. Here you see I included ProductVersion you asked for. There are other predefined values. See Microsoft documentation.

You should add error testing that I omitted for example simplicity.