Получить FileVersion с Build

DelphiXe.

Для получения версии файла я использую функцию:

function FileVersion(AFileName: string): string;
var
  szName: array[0..255] of Char;
  P: Pointer;
  Value: Pointer;
  Len: UINT;
  GetTranslationString: string;
  FFileName: PChar;
  FValid: boolean;
  FSize: DWORD;
  FHandle: DWORD;
  FBuffer: PChar;
begin
  try
    FFileName := StrPCopy(StrAlloc(Length(AFileName) + 1), AFileName);
    FValid := False;
    FSize := GetFileVersionInfoSize(FFileName, FHandle);
    if FSize > 0 then
    try
      GetMem(FBuffer, FSize);
      FValid := GetFileVersionInfo(FFileName, FHandle, FSize, FBuffer);
    except
      FValid := False;
      raise;
    end;
    Result := '';
    if FValid then
      VerQueryValue(FBuffer, '\VarFileInfo\Translation', p, Len)
    else
      p := nil;
    if P <> nil then
      GetTranslationString := IntToHex(MakeLong(HiWord(Longint(P^)),
        LoWord(Longint(P^))), 8);
    if FValid then
    begin
      StrPCopy(szName, '\StringFileInfo\' + GetTranslationString +
        '\FileVersion');
      if VerQueryValue(FBuffer, szName, Value, Len) then
        Result := StrPas(PChar(Value));
    end;
  finally
    try
      if FBuffer <> nil then
        FreeMem(FBuffer, FSize);
    except
    end;
    try
      StrDispose(FFileName);
    except
    end;
  end;
end;

Для большинства исполняемых файлов и библиотек возвращает правильное значение. Но у некоторых файлов версия обрезается и показывается без сборки. Вот например файл BASS.DLL (http://us.un4seen.com/files/bass24.zip) В проводнике Windows в свойствах файла я вижу версию 2.4.7.1, функция result='2.4.7':(

Я открываю файл через Resourcehacker.exe (http://angusj.com/resourcehacker/), смотрю структуру VersionInfo:

1 VERSIONINFO
FILEVERSION 2,4,7,1
PRODUCTVERSION 2,4,0,0
FILEOS 0x4
FILETYPE 0x2
{
BLOCK "StringFileInfo"
{
    BLOCK "000004b0"
    {
        VALUE "CompanyName", "Un4seen Developments"
        VALUE "FileDescription", "BASS"
        VALUE "FileVersion", "2.4.7"
        VALUE "LegalCopyright", "Copyright © 1999-2010"
    }
}

BLOCK "VarFileInfo"
{
    VALUE "Translation", 0x0000 0x04B0
}
}

Вопрос: как получить 2.4.7.1, т.е. полную версию?

2 ответа

Решение

Если вам нужна версия файла корневого блока, тогда забудьте о переводе на конкретный язык:

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;

Если вы хотите редактировать аудио библиотеку BASS (чего вы не можете). Причина в том, что он сжат "Petite v1.4", который хочет Ян, чтобы люди не могли его легко редактировать.

Кроме того, для получения версии bass.dll есть экспорт, который при использовании вы можете получить абсолютную версию, как вы хотите без большого взлома, а что нет.

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