//-------------------------------------------------------------------------
// Copyright (c) 1999 - Sortland Automasjon <automasjon@sortland.net>
//
// All Rights Reserved
//
// web: http://www.sortland.net         fax: +47 5342 0281
//
// Download project: sortland.net/Delphi/Snippets/VersionInfo.zip
//-------------------------------------------------------------------------
{$DEFINE DELPHI_4}

unit VersionInfoSmall;  // Read file version information from EXE file

interface

uses
  Windows, SysUtils;

const
  vsCompanyName       = 'CompanyName';
  vsFileDescription   = 'FileDescription';
  vsFileVersion       = 'FileVersion';
  vsInternalName      = 'InternalName';
  vsOriginalFilename  = 'OriginalFilename';
  vsProductName       = 'ProductName';
  vsProductVersion    = 'ProductVersion';
  vsLegalCopyright    = 'LegalCopyright';
  vsLegalTrademarks   = 'LegalTrademarks';
  vsComments          = 'Comments';
  vsPrivateBuild      = 'PrivateBuild';
  vsSpecialBuild      = 'SpecialBuild';

type
{$IFDEF DELPHI_4}
  INT_Cardinal = Cardinal;
{$ELSE}
  INT_Cardinal = Integer;
{$ENDIF}

  TFileInfo = (
    aFileVersion, aFileVersionLong
    {, aProductVersion, aProductVersionLong }
    );

function GetVersionString(const vsKey: string): string;
function GetFileVersion(const fInfo: TFileInfo): string;

implementation

var
  VerInfoPresent: Boolean; // True if "fVerBuffer" contains valid information
  fVerBuffer: Pointer;     // The file information is stored in this location

function SwapLong(L: LongInt): LongInt; assembler;
asm
  rol eax, 16;
end;

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// GetVersionString(vsCompanyName); returns "Sortland Automasjon"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function GetVersionString(const vsKey: string): string;
var
  zKeyPath: array[0..255] of Char;
  p: Pointer;
  Len: INT_Cardinal;
begin
  Result := '';
  if not VerInfoPresent then Exit;

  if VerQueryValue(fVerBuffer, '\VarFileInfo\Translation', p, Len) then
    begin
      StrLFmt(zKeyPath, 255, '\StringFileInfo\%.8x\%s',
        [SwapLong(LongInt(p^)), vsKey]);
      if VerQueryValue(fVerBuffer, zKeyPath, p, Len) then
        Result := strPas(PChar(p));
    end;
end;

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// GetFileVersion(aFileVersionLong); returns "1.0.1.43"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function GetFileVersion(const fInfo: TFileInfo): string;
var
  Len: INT_Cardinal;
  pVerInfo: PVSFixedFileInfo;
begin
  Result := '';
  if not VerInfoPresent then Exit;

  if VerQueryValue(fVerBuffer, '\', Pointer(pVerInfo), Len) then
    begin
      case fInfo of
        aFileVersion:
          Result := IntToStr(HIWORD(pVerInfo.dwFileVersionMS))
            + '.' + IntToStr(LOWORD(pVerInfo.dwFileVersionMS));
        aFileVersionLong:
          Result := IntToStr(HIWORD(pVerInfo.dwFileVersionMS))
            + '.' + IntToStr(LOWORD(pVerInfo.dwFileVersionMS))
            + '.' + IntToStr(HIWORD(pVerInfo.dwFileVersionLS))
            + '.' + IntToStr(LOWORD(pVerInfo.dwFileVersionLS));
      end;
    end;
end;

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Here is where the information is actually read from the EXE file.
// Data is read once, when the unit is initialized, and stored in 'fVerBuffer'
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var
  fn: array[0..MAX_PATH] of Char;
  sz: Integer;
  fVersionHandle: INT_Cardinal;

initialization
  VerInfoPresent := False;

  StrPLCopy(fn, ParamStr(0), MAX_PATH); // Application.ExeName

  sz := GetFileVersionInfoSize(fn, fVersionHandle);
  GetMem(fVerBuffer, sz);
  if (sz > 0) and GetFileVersionInfo(fn, 0, sz, fVerBuffer) then
    VerInfoPresent := True;

finalization
  FreeMem(fVerBuffer, sz);
end.

Delphi Snippets - may 1999 - Arnulf Sortland