更改可执行文件中的内部版本号



我想更改可执行文件版本信息中的内部版本号(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);

因此,第一个StringStruct的信息似乎是正确的。但由于szKey和Value都不是固定大小的,我不知道如何正确定义我的压缩记录(有可能吗?)来获得这些值。我的数组也有问题。。。我该如何定义它们?按照我的方式,我只是在每个结构上得到第一个孩子。注意,我忽略了填充。。。这样可以吗?

感谢您的帮助。我在这里做的大部分都是试错,所以我真的不明白发生了什么

附言:我还在写这篇文章,所以我可能会经常更新这篇文章。

我感谢您的关注和帮助。我在SO上找到了一个现成的解决方案。事实上,它就在我所联系的问题的评论中(我真丢脸!)。

它是以科林·威尔逊的图书馆为蓝本的。它使用指针算法来提取和写入信息,所以,这是一种困难的(可能只是)方法。还有一个关于如何使用库的好例子,作者是JasonPenny:SetVersion。由于我使用D7,我从这里下载了Colin Wilson的库(在Resource Utilities下),但这里提供了使用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。

最新更新