【问题标题】:Extracting the ProductVersion from the compiled executable/package从已编译的可执行文件/包中提取 ProductVersion
【发布时间】:2020-10-27 09:37:08
【问题描述】:

Project Options中,可以为编译后的文件设置一些信息,比如:

  • 公司名称
  • 文件说明
  • 文件版本
  • 内部名称
  • 法律版权
  • 合法商标
  • 原始文件名
  • 产品名称
  • 产品版本
  • 评论

我在运行时从编译文件(exe/bpl)中知道how to extract the file version,但我不知道如何提取这些额外信息。

我特别想得到 ProductVersion

【问题讨论】:

  • 你看到这个问题了吗? :stackoverflow.com/questions/1717844/…
  • @Charles-Henri:这是一个不同的问题,但我注意到 Jiri Krivanek 的回答也适合我的问题
  • VERSIONINFO 中最多可以存储 两个 产品版本记录。第一个存储为TVSFixedFileInfo 中的数字(2 个DWORD),第二个存储为StringFileInfoProductVersion 键下的字符串。后者可以不限于数字,还可以包含其他信息,如 BETARC1
  • @PeterWolf:我正在寻找存储在StringFileInfo 中的区域设置ID $0409(我想......)但是我在哪里可以找到关于这两种文件的一些信息信息?
  • 查看我已经发布的 VERSIONINFO 资源的官方 MS 文档。另请参阅文档导航窗格中的子类别 StringFileInfo 块。

标签: delphi delphi-xe7


【解决方案1】:

下面是从可执行文件(或给定文件名的任何文件)中获取 ProductVersion 的代码:

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;

代码首先通过查询可用的语言,然后遍历所有可用的语言。

SubBlock实际上是一种值查询的路径。在这里,您看到我包含了您要求的ProductVersion。还有其他预定义的值。请参阅 Microsoft documentation

为了简单起见,您应该添加我省略的错误测试。

【讨论】:

  • 注意:与想要枚举块中的所有值相比,这几乎是微不足道的事情。同样,ProductVersion 也不能保证存在于 StringFileInfo 块中。
猜你喜欢
  • 2012-08-20
  • 2012-12-26
  • 1970-01-01
  • 2011-05-01
相关资源
最近更新 更多