1

GetFileVersionInfoSize is 0 (zero) And GetFileVersionInfo return nothing

I am using it Like this:

function FileVersion(const FileName: TFileName): String;
var
  VerInfoSize: Cardinal;
  VerValueSize: Cardinal;
  Dummy: Cardinal;
  PVerInfo: Pointer;
  PVerValue: PVSFixedFileInfo;
begin
  Result := '';
  VerInfoSize := GetFileVersionInfoSize(PChar(FileName), Dummy);
  GetMem(PVerInfo, VerInfoSize);
  try
    if GetFileVersionInfo(PChar(FileName), 0, VerInfoSize, PVerInfo) then
      if VerQueryValue(PVerInfo, '\', Pointer(PVerValue), VerValueSize) then
        with PVerValue^ do
          Result := Format('v%d.%d.%d build %d', [
            HiWord(dwFileVersionMS), //Major
            LoWord(dwFileVersionMS), //Minor
            HiWord(dwFileVersionLS), //Release
            LoWord(dwFileVersionLS)]); //Build
  finally
    FreeMem(PVerInfo, VerInfoSize);
  end;
end;

Based on the stack reply Get FileVersion with Build

It work in most of the cases.

Thanks

Community
  • 1
  • 1
Jlouro
  • 4,515
  • 9
  • 60
  • 91
  • You're not checking to see if `GetFileVersionInfoSize` returned a useful value (VerInfoSize > 0). You're also not checking the return value of `GetFileVersionInfo`. Add an `else` to that, and see what `GetLastError` tells you. – Ken White Jun 24 '13 at 16:44
  • Yes I see that. But if the file exist int correct Path, what could let the GetFileVersionInfoSize to return 0 ? – Jlouro Jun 24 '13 at 21:32
  • Again, you need to call `GetLastError()` to find out why it is returning 0. Most likely, the file simply does not have any version info available in the first place. – Remy Lebeau Jun 24 '13 at 22:15

1 Answers1

5

You're not checking the return value of GetFileVersionInfoSize. If the file name is invalid or there's no version info available, it will return zero (false), and the documentation says you can find out why using GetLastError. As you're using Delphi 2007, cross-platform compatibility isn't an issue (at least for now), and you can use SysErrorMessage(GetLastError) to get a string description of the reason it failed.

I've written it to return the error message if something fails; in an actual application, you probably won't want to do that, of course.

This works (tested on Delphi 7, Win7 64-bit):

function FileVersion(const FileName: TFileName): String;
var
  VerInfoSize: Cardinal;
  VerValueSize: Cardinal;
  Dummy: Cardinal;
  PVerInfo: Pointer;
  PVerValue: PVSFixedFileInfo;
  iLastError: DWord;
begin
  Result := '';
  VerInfoSize := GetFileVersionInfoSize(PChar(FileName), Dummy);
  if VerInfoSize > 0 then
  begin
    GetMem(PVerInfo, VerInfoSize);
    try
      if GetFileVersionInfo(PChar(FileName), 0, VerInfoSize, PVerInfo) then
      begin
        if VerQueryValue(PVerInfo, '\', Pointer(PVerValue), VerValueSize) then
          with PVerValue^ do
            Result := Format('v%d.%d.%d build %d', [
              HiWord(dwFileVersionMS), //Major
              LoWord(dwFileVersionMS), //Minor
              HiWord(dwFileVersionLS), //Release
              LoWord(dwFileVersionLS)]); //Build
      end
      else
      begin
        iLastError := GetLastError;
        Result := Format('GetFileVersionInfo failed: (%d) %s', 
                      [iLastError, SysErrorMessage(iLastError)]);
      end;
    finally
      FreeMem(PVerInfo, VerInfoSize);
    end;
  end
  else
  begin
    iLastError := GetLastError;
    Result := Format('GetFileVersionInfo failed: (%d) %s', 
                     [iLastError, SysErrorMessage(iLastError)]);
  end;
end;

Always test the return value of WinAPI calls. The documentation at MSDN describes the return values and reasons for failure (or tells you that you can get it from GetLastError).

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • If you are going to display an error message, it is usually helpful to include the actual error code in the message, eg: `var iLastError: Integer; ... iLastError := GetLastError; Result := Format('GetFileVersionInfoSize failed: (%d) %s', [iLastError, SysErrorMessage(iLastError)]);` – Remy Lebeau Jun 24 '13 at 22:18
  • @Remy: You're right, of course. Edited to implement your suggestion. Thanks. – Ken White Jun 24 '13 at 22:23