0

I'm updating a program to Delphi XE7 from Delphi 2010. The code shown below has stopped working due I think to the need to adapt for unicode and to use GetFileVersionInfoW instead of GetFileVersionInfoSize.

Has anyone developed a more up-to-date version of the function I was using shown below? I can't find any examples so far on the web and I'm afraid that low level windows programming is a bit beyond me.

Thanks for any help!

Old Code Below No Longer works on Delphi XE2 and later: just returns 1.0.0.0

procedure GetBuildInfo(var V1, V2, V3, V4: Word);
{From Steve Schafer }
var
  VerInfoSize: DWORD;
  VerInfo: pointer;
  VerValueSize: DWORD;
  VerValue: PVSFixedFileInfo;
  Dummy: DWORD;

begin
  VerInfoSize := GetFileVersionInfoSize(PChar(ParamStr(0)), Dummy);
  GetMem(VerInfo, VerInfoSize);
  GetFileVersionInfo(PChar(ParamStr(0)), 0, VerInfoSize, VerInfo);
  VerQueryValue(VerInfo, '\', pointer(VerValue), VerValueSize);
  with VerValue^ do
    begin
      V1 := dwFileVersionMS shr 16;
      V2 := dwFileVersionMS and $FFFF;
      V3 := dwFileVersionLS shr 16;
      V4 := dwFileVersionLS and $FFFF;
    end;
  FreeMem(VerInfo, VerInfoSize);
end;
CHEAPS
  • 179
  • 3
  • 13
  • 3
    Are you sure your app. is not of version 1.0.0.0 ? Btw. you should definitely add some error checking. – TLama Dec 04 '14 at 23:17
  • The code you posted works perfectly fine in a new VCL app in XE6. Drop a label on the form, go to project options and set the version info for the build, add a handler for FormShow with these two lines (and the appropriate variable declarations): GetBuildInfo(Major, Minor, Rev, Build); Label1.Caption := Format('%d.%d.%d.%d', [Major, Minor, Rev, Build]); Project->Build (to get the version info added, and run the app. In my case, I set the version to 4.3.2.1, and the label shows `4.3.2.1`. – Ken White Dec 04 '14 at 23:21
  • 1
    The code works exactly the same on all versions of Delphi. The lack of error checking isn't ideal. – David Heffernan Dec 04 '14 at 23:28
  • 1
    The RTL maps Win32 API functions to match the data type used for `(P)Char`. Thus, `GetFileVersionInfoSize()` and `GetFileVersionInfo()` actually map to `GetFileVersionInfoSizeA()` and `GetFileVersionInfoA()` in Delphi 2007 and earlier, and map to `GetFileVersionInfoSizeW()` and `GetFileVersionInfoW()` in Delphi 2009 and later. That is why this code works in every Delphi version without any modification. – Remy Lebeau Dec 04 '14 at 23:40
  • Thanks - I'm not sure what happened but it was always returning 1.0.0.0 even though I had different fileversions set. However, I notice that the product version and a few other fields were missing and once I typed those back in to the IDE the function started working again. So thanks for confirming and pointing me in the right direction. – CHEAPS Dec 04 '14 at 23:44
  • 1
    Personally, when retrieving the calling app's own version number, I prefer to load the version resource directly instead of using `GetFileVersionInfo()`: http://stackoverflow.com/a/13942403/65863 – Remy Lebeau Dec 04 '14 at 23:44
  • @Cheaps, you are not probably not taking into account that different build configurations have their own version resource. When you change one, you have to change them all. The IDE doesn't do a good job of managing multiple-build version resources, but there are tools and add-ons that make it easier to work with. – Remy Lebeau Dec 04 '14 at 23:46

1 Answers1

3

Your code works perfectly well when compiled by all versions of Delphi. The only logical conclusion therefore, as to why the code reports a version of 1.0.0.0 is that the version is 1.0.0.0.

In other words your problem will not be found by looking at this code. Your problem will be found by working out why you are not managing to set the version information a you intend when compiling.

It is probably also worth pointing out that your code makes no attempt to check return values for errors.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490