【问题标题】:Change build number in an executable更改可执行文件中的内部版本号
【发布时间】:2014-02-12 16:41:06
【问题描述】:

我希望在可执行文件的版本信息中更改内部版本号(VersionLS 的低阶)。所以,我应该阅读VS_VERSIONINFO 结构,更改内部版本号,然后将其更新回PE。

我正在使用此代码作为基础:https://stackoverflow.com/a/7999813/1970843。这段代码非常适合更改VS_FIXEDFILEINFO 数据,但它不会更改(也不会访问)StringFileInfo 信息。

我很确定我应该在 VERSIONHEADER 打包记录中包含一些内容以添加 VS_VERSIONINFO 的 Children 条目,但我不知道具体该怎么做。这是我目前所拥有的:

type
    StringStruc = Packed Record
        wLength: Word;
        wValueLength: Word;
        wType: Word;
        //szKey: ?;
        //Value: ?;
    End;

    StringTable = Packed Record
        wLength: Word;
        wValueLength: Word;
        wType: Word;
        szKey: Array[0..8] Of WideChar;
        Children: StringStruc;
    End;

    StringFileInfo = Packed Record
        wLength: Word;
        wValueLength: Word;
        wType: Word;
        szKey: Array[0..14] Of WideChar;   // 'STRINGFILEINFO'
        Children: StringTable;
    End;

    VERSIONHEADER = Packed Record
        wLength: Word;
        wValueLength: Word;
        wType: Word;
        szKey: Array[0..16] Of WideChar;   // 'VS_VERSION_INFO'
        Version: VS_FIXEDFILEINFO;
        Children: StringFileInfo;
    End;

...

var VersionHandle, VersionRes: THandle;
    VersionSize: Cardinal;
    Version: Array Of AnsiChar;
    Ver: ^VERSIONHEADER;
Begin
    VersionSize := GetFileVersionInfoSize(PChar(sExe), VersionHandle);

    SetLength(Version, VersionSize);
    Ver := Pointer(Version);
    GetFileVersionInfo(PChar(sExe), 0, VersionSize, Ver);

因此,信息似乎正确地传递到第一个 StringStruc。但是由于 szKey 和 Value 都不是固定大小,我不知道如何正确定义我的打包记录(甚至可能吗?)来获取这些值。我也遇到了数组问题......我该如何定义它们?我正在做的方式是,我只是在每个 Struc 上获得第一个孩子。请注意,我忽略了填充...可以吗?

感谢任何帮助。我在这里所做的大部分工作都是反复试验,所以我不太明白发生了什么。

PS:我还在努力,所以我可能会经常更新这篇文章。

【问题讨论】:

  • 也许我应该尝试将内存作为原始二进制数据读取?当我找到我想要更改的内容时,我需要更新每个父母的信息和大小,并根据需要重新分配内存......听起来很难。
  • 对于一个项目,我尝试更改 StringFileInfo,但它远非显而易见,AFAIR。结果,我坚持更改数字信息(您的问题中已链接的代码:)),并将通用文本放在字符串字段中。重要的是“关于”框和初始屏幕(从数字字段中提取)中显示的内容,以及文件属性是否给出了确切的(数字)“文件版本”(例如 2.1.231),但对于“产品版本”(例如“2”或“2.1”)——对我来说已经足够了。
  • 你不能用BeginUpdateResource等来做吗?
  • @DavidHeffernan 不,遗憾的是他不能。这就是重点。请参阅他关于 BeginUpdateResource 的链接 - 它适用于数字版本,但不适用于字符串版本:分配这样的资源结构并不明显。
  • 与其重新发明轮子,不如使用 StampVer,让它为您完成艰苦的工作。 (这是一个应用程序。但对我们来说仍然可以正常工作。)codeguru.com/tools/standalonetools/article.php/c1403/…

标签: delphi winapi binary patch versioninfo


【解决方案1】:

感谢您的关注和帮助。我在这里找到了一个现成的解决方案。事实上,我所链接的问题就在 cmets 中(真丢脸!)。

它基于Colin Wilson 的库。它使用指针算法来提取和写入信息,因此是硬(也许是唯一的)方式。 Jason Penny 还提供了一个关于如何使用该库的好例子:SetVersion。因为我使用的是 D7,所以我从 here(在 Resource Utilities 下)下载了 Colin Wilson 的库,但是here 提供了使用 UnicodeString 和更好的指针算法的更新版本。

这是我现在的实际实现:

uses ..., unitResourceVersionInfo, unitPEFile;

...

var VersionInfo: TVersionInfoResourceDetails;
    PEResModule: TPEResourceModule;
    VersionNumber: ULARGE_INTEGER;
    sVersion: String;
    I: Integer;
Begin
    PEResModule := TPEResourceModule.Create;
    Try
        PEResModule.LoadFromFile(sExe);

        For I := 0 To PEResModule.ResourceCount - 1 Do Begin
            If PEResModule.ResourceDetails[I] Is TVersionInfoResourceDetails Then Begin
                VersionInfo := (PEResModule.ResourceDetails[I] As TVersionInfoResourceDetails);
                Break;
            End;
        End;

        VersionNumber.LowPart := MakeLong(NewBuildNumber, HiWord(VersionInfo.FileVersion.LowPart));
        VersionNumber.HighPart := VersionInfo.FileVersion.HighPart;
        VersionInfo.FileVersion := VersionNumber;
        VersionInfo.ProductVersion := VersionNumber;

        VersionInfo.CodePage := $04e4;

        sVersion := Format('%d.%d.%d.%d', [HiWord(VersionInfo.FileVersion.HighPart), LoWord(VersionInfo.FileVersion.HighPart), HiWord(VersionInfo.FileVersion.LowPart), LoWord(VersionInfo.FileVersion.LowPart)]);
        VersionInfo.SetKeyValue('FileVersion', sVersion);

        PEResModule.SaveToFile(ChangeFileExt(sExe, '.exe2'));

    Finally
        FreeAndNil(PEResModule);
    End;
End;

代码页行是由于库中的一个错误(我相信是)。它不读取代码页(为 0),因此,当您保存回来时,它显示为 0。

【讨论】:

    猜你喜欢
    • 2013-11-07
    • 2013-03-18
    • 2014-09-30
    • 2021-04-26
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多