Delphi 从已编译的可执行文件/包中提取ProductVersion

Delphi 从已编译的可执行文件/包中提取ProductVersion,delphi,delphi-xe7,Delphi,Delphi Xe7,在项目选项中,可以为已编译文件设置一些信息,如: 公司名称 文件描述 文件版本 内部名称 法律权利 商标 原始文件名 产品名称 产品版本 评论 我从运行时的编译文件(exe/bpl)中知道,但我不知道如何提取这些额外信息 特别是,我希望获得ProductVersion值 下面是从可执行文件(或给定其文件名的任何文件)中获取ProductVersion的代码: 类型 TLangAndCodePage=记录 语言:单词; wCodePage:WORD; 结束; PLangAndCodePage=

在项目选项中,可以为已编译文件设置一些信息,如:

  • 公司名称
  • 文件描述
  • 文件版本
  • 内部名称
  • 法律权利
  • 商标
  • 原始文件名
  • 产品名称
  • 产品版本
  • 评论
我从运行时的编译文件(exe/bpl)中知道,但我不知道如何提取这些额外信息

特别是,我希望获得ProductVersion值


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

类型
TLangAndCodePage=记录
语言:单词;
wCodePage:WORD;
结束;
PLangAndCodePage=^TLangAndCodePage;
程序TForm1.按钮1单击(发送方:TObject);
变量
InfoSize:整数;
ValueSize:DWORD;
假人:德沃德;
VerInfo:指针;
LangAndCodePage:PLangAndCodePage;
Ptr:PLangAndCodePage;
翻译字节:UINT;
I:整数;
子块:字符串;
子块缓冲区:PChar;
开始
InfoSize:=GetFileVersionInfoSize(PChar(Application.ExeName),Dummy);
如果InfoSize为0,则开始
GetMem(VerInfo,InfoSize);
尝试
如果GetFileVersionInfo(PChar(Application.ExeName),则为0,
InfoSize,VerInfo)然后开始
VerQueryValue(VerInfo,
“\VarFileInfo\Translation”,
指针(LangAndCodePage),
翻译细胞);
Ptr:=LangAndCodePage;
对于I:=0到(TranslateBytes div SizeOf(TLangAndCodePage))-1不开始
子块:=格式(“\StringFileInfo\%04.4X%04.4X\ProductVersion”,
[Ptr.w语言,Ptr.w代码页];
备注1.行.添加(子块);
VerQueryValue(VerInfo,
PChar(子块),
指针(子块缓冲区),
价值大小);
Memo1.Lines.Add('ProductVersion=“”+SubBlockBuffer+”);
公司(Ptr);
结束;
结束;
最后
FreeMem(VerInfo,InfoSize);
结束;
结束;
结束;
首先查询可用语言,然后遍历所有可用语言,从而生成代码

子块
实际上是要查询的值的一种路径。在这里,您可以看到我包含了您要求的
ProductVersion
。还有其他预定义的值。见微软


您应该添加我忽略的错误测试,例如简单性。

您看到这个问题了吗@Charles Henri:这是一个不同的问题,但我注意到Jiri Krivanek的回答也适用于我的问题,其中最多可以存储两个产品版本记录。第一个作为数字(2个DWORDs)存储在
TVSFixedFileInfo
中,第二个作为字符串存储在
StringFileInfo
ProductVersion
键下。后者可以不限于数字,还可以包含其他信息,如BETA或RC1。@彼得沃尔夫:我正在查找存储在
StringFileInfo
中的区域设置ID
$0409
(我想…)但我在哪里可以找到关于这两种文件信息的一些信息呢?请参阅官方MS文档以获取我已经发布的资源。另请参见文档导航窗格中的子类别块。注意:与在不知道其名称的情况下枚举块中的所有值相比,这几乎是微不足道的事情。同样地,
ProductVersion
也不能保证存在于
StringFileInfo
块中。
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;