GetFileVersionInfoSize и GetFileVersionInfo ничего не возвращают

GetFileVersionInfoSize равен 0 (нулю), а GetFileVersionInfo ничего не возвращает

Я использую это так:

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;

На основе ответа стека Получить FileVersion с Build

Это работает в большинстве случаев.

Спасибо

1 ответ

Решение

Вы не проверяете возвращаемое значение GetFileVersionInfoSize, Если имя файла неверно или информация о версии недоступна, он вернет ноль (false), и в документации сказано, что вы можете узнать, почему GetLastError, Поскольку вы используете Delphi 2007, кросс-платформенная совместимость не является проблемой (по крайней мере, на данный момент), и вы можете использовать SysErrorMessage(GetLastError) чтобы получить строковое описание причины, по которой это не удалось.

Я написал это, чтобы вернуть сообщение об ошибке, если что-то не так; в реальном приложении вы, вероятно, не захотите этого делать, конечно.

Это работает (проверено на 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;

Всегда проверяйте возвращаемое значение вызовов WinAPI. Документация в MSDN описывает возвращаемые значения и причины сбоя (или говорит, что вы можете получить его из GetLastError).

Другие вопросы по тегам