I'm looking to change the build number (low-order of VersionLS) in the version info of an executable. So, I should read the VS_VERSIONINFO structure, change the build number and then update it back to the PE.
I'm working with this code as base: https://stackoverflow.com/a/7999813/1970843. This code works really well to change the VS_FIXEDFILEINFO data, but it doesn't changes (nor access) the StringFileInfo information.
I'm pretty sure I should include something in the VERSIONHEADER packed record to add the Children entry of VS_VERSIONINFO, but I don't know exactly how to do this. This is what I have so far:
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);
So, the information seems to be coming correctly up to the first StringStruc. But since both szKey and Value aren't fixed size, I don't know how to correctly define my Packed Record (is it even possible?) to get those values. I'm also having troubles with the arrays... how can I define them? The way I'm doing, I'm just getting the first Children on each Struc. Notice that I'm ignoring the paddings... is this ok?
Any help is appreciated. Most of what I've done here was by trial and error, so I don't really understand what's going on.
PS: I'm still working on this, so I might update this post frequently.
I appreciate your attention and help. I found a ready solution here on SO. In fact, it's in the comments to the very question I've linked to (shame on me!).
It's based on a library by Colin Wilson. It uses pointer arithmetic to extract and write the information, so, the hard (maybe only) way. There's also a nice example on how to use the library by Jason Penny: SetVersion. Since I'm using D7, I downloaded Colin Wilson's library from here (under Resource Utilities), but a more recent version, using UnicodeString and nicer pointer arithmetic, is available here.
This is the actual implementation I have now:
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;
The codepage line is due to a bug (I believe it is) in the library. It doesn't reads the codepage (comes 0), so, when you save back, it appears as 0.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With