Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is most likely no translated for the post!




Share:
Notifications
Clear all

Lazarus - How to use (and extract) version info cross platform


 Hans
(@hans)
Noble Member Admin
Joined: 8 years ago
Posts: 1832
Topic starter  

As you might know; in Lazarus you can add version and build info to the executable (at least under Linux, Windows, and MacOS X).
The question is - for example for an About box - how do I extract that information from my executable at runtime? And ... preferably cross platform.

Follow these steps:

1. Add units vinfo (step 3 creates the unit) and versiontypes to the Uses clause.

2. Add code to one of the forms (typically the main form so you can read it if you make it a property of tform).

As you can see in the code below, version info can be extracted from the TVersionInfo object:

  ...
var Info: TVersionInfo;
Version: string;
begin
// Get application compiled version#
Info := TVersionInfo.Create;
Info.Load(HINSTANCE);
Version := Format('%d.%d.%d', [Info.FixedInfo.FileVersion[0],Info.FixedInfo.FileVersion[1],Info.FixedInfo.FileVersion[2]]);
Info.Free;
self.Caption:='Name My TV Series v'+Version+' - © Hans Luijten - www.tweaking4all.com';
...

3. Create and save the file vinfo.pas (which we added to the sues clause in step 1).

unit vinfo;
{$mode objfpc}
interface
uses
Classes, SysUtils, resource, versiontypes, versionresource;
type
{ TVersionInfo }
TVersionInfo = class
private
FVersResource: TVersionResource;
function GetFixedInfo: TVersionFixedInfo;
function GetStringFileInfo: TVersionStringFileInfo;
function GetVarFileInfo: TVersionVarFileInfo;
function SearchValue(const aString : string) : string;
public
constructor Create;
destructor Destroy; override;
function CompanyName : string;
function InternalName : string;
function FileVersion : string;
function ProductName : string;
procedure Load(Instance: THandle);
property FixedInfo: TVersionFixedInfo read GetFixedInfo;
property StringFileInfo: TVersionStringFileInfo read GetStringFileInfo;
property VarFileInfo: TVersionVarFileInfo read GetVarFileInfo;
end;
implementation
{ TVersionInfo }
function TVersionInfo.GetFixedInfo: TVersionFixedInfo;
begin
Result := FVersResource.FixedInfo;
end;
function TVersionInfo.GetStringFileInfo: TVersionStringFileInfo;
begin
Result := FVersResource.StringFileInfo;
end;
function TVersionInfo.GetVarFileInfo: TVersionVarFileInfo;
begin
Result := FVersResource.VarFileInfo;
end;
function TVersionInfo.SearchValue(const aString: string): string;
var s : TVersionStringTable;
i,j : integer;
begin
result := '';
for i:=0 to StringFileInfo.Count-1 do begin
s := StringFileInfo.Items;
for j:=0 to s.Count-1 do
if s.Keys[j] = aString then begin
result := s.Values[j];
break;
end;
end;
end;
function TVersionInfo.CompanyName: string;
begin
Result := SearchValue('CompanyName');
end;
function TVersionInfo.InternalName: string;
begin
Result := SearchValue('InternalName');
end;
function TVersionInfo.FileVersion: string;
begin
Result := SearchValue('FileVersion');
end;
function TVersionInfo.ProductName: string;
begin
Result := SearchValue('ProductName');
end;
constructor TVersionInfo.Create;
begin
inherited Create;
FVersResource := TVersionResource.Create;
Load(HInstance);
end;
destructor TVersionInfo.Destroy;
begin
FVersResource.Free;
inherited Destroy;
end;
procedure TVersionInfo.Load(Instance: THandle);
var
Stream: TResourceStream;
begin
Stream := TResourceStream.CreateFromID(Instance, 1, PChar(RT_VERSION));
try
FVersResource.SetCustomRawDataStream(Stream);
// access some property to load from the stream
FVersResource.FixedInfo;
// clear the stream
FVersResource.SetCustomRawDataStream(nil);
finally
Stream.Free;
end;
end;
end.


ReplyQuote
 Hans
(@hans)
Noble Member Admin
Joined: 8 years ago
Posts: 1832
Topic starter  

An improved vinfo.pas (typo in the previous version):

unit vinfo;
{$mode objfpc}
interface
uses
  Classes, SysUtils, resource, versiontypes, versionresource;
type
  { TVersionInfo }
  TVersionInfo = class
  private
    FVersResource: TVersionResource;
    function GetFixedInfo: TVersionFixedInfo;
    function GetStringFileInfo: TVersionStringFileInfo;
    function GetVarFileInfo: TVersionVarFileInfo;
    function SearchValue(const aString : string) : string;
  public
    constructor Create;
    destructor Destroy; override;
    function CompanyName : string;
    function InternalName : string;
    function FileVersion : string;
    function ProductName : string;
    procedure Load(Instance: THandle);
    property FixedInfo: TVersionFixedInfo read GetFixedInfo;
    property StringFileInfo: TVersionStringFileInfo read GetStringFileInfo;
    property VarFileInfo: TVersionVarFileInfo read GetVarFileInfo;
  end;
implementation
{ TVersionInfo }
function TVersionInfo.GetFixedInfo: TVersionFixedInfo;
begin
  Result := FVersResource.FixedInfo;
end;
function TVersionInfo.GetStringFileInfo: TVersionStringFileInfo;
begin
  Result := FVersResource.StringFileInfo;
end;
function TVersionInfo.GetVarFileInfo: TVersionVarFileInfo;
begin
  Result := FVersResource.VarFileInfo;
end;
function TVersionInfo.SearchValue(const aString: string): string;
var s : TVersionStringTable;
    i,j : integer;
begin
  result := '';
  for i:=0 to StringFileInfo.Count-1 do begin
      s := StringFileInfo.Items;
      for j:=0 to s.Count-1 do
          if s.Keys[j] = aString then begin
             result := s.Values[j];
             break;
          end;
  end;
end;
function TVersionInfo.CompanyName: string;
begin
   Result := SearchValue('CompanyName');
end;
function TVersionInfo.InternalName: string;
begin
   Result := SearchValue('InternalName');
end;
function TVersionInfo.FileVersion: string;
begin
   Result := SearchValue('FileVersion');
end;
function TVersionInfo.ProductName: string;
begin
   Result := SearchValue('ProductName');
end;
constructor TVersionInfo.Create;
begin
  inherited Create;
  FVersResource := TVersionResource.Create;
  Load(HInstance);
end;
destructor TVersionInfo.Destroy;
begin
  FVersResource.Free;
  inherited Destroy;
end;
procedure TVersionInfo.Load(Instance: THandle);
var
  Stream: TResourceStream;
begin
  Stream := TResourceStream.CreateFromID(Instance, 1, PChar(RT_VERSION));
  try
    FVersResource.SetCustomRawDataStream(Stream);
    // access some property to load from the stream
    FVersResource.FixedInfo;
    // clear the stream
    FVersResource.SetCustomRawDataStream(nil);
  finally
    Stream.Free;
  end;
end;
end.


ReplyQuote
 Hans
(@hans)
Noble Member Admin
Joined: 8 years ago
Posts: 1832
Topic starter  

Christian Lafin has graciously offered his version to be posted on this forum , this unit uses the VersionInfo_Class unit posted above and makes a few calls easier.

unit Versionfunctions_Unit;
{$mode objfpc}{$H+}
//##############################################################################
// Autor: Christian Lafin ( http://lafin.de) //
// using VersionInfo_Class found here: //www.tweaking4all.com/forums/topic/lazarus-how-to-use-and-extract-version-info-cross-platform/
// Version: 0.1.0.1 //
// Changelog: //
// Update 1/2015, Version 0.1.0.1 , ProductNameAsString(), //
// FileVersionAsString(), //
// ProductVersionAsString //
//##############################################################################
interface
uses
  Classes, SysUtils, resource, VersionInfo_Class;
function ProductVersionAsString(): String;
function FileVersionAsString(): String;
function ProductNameAsString(): String;
implementation
function ProductNameAsString(): String;
var
   VerInfo: TVersionInfo;
begin
   VerInfo := TVersionInfo.Create();
   VerInfo.Load(HINSTANCE);
   Result := VerInfo.ProductName();
   VerInfo.Free();
end;
function FileVersionAsString(): String;
var
   VerInfo: TVersionInfo;
begin
   VerInfo := TVersionInfo.Create();
   VerInfo.Load(HINSTANCE);
   Result := IntToStr(VerInfo.FixedInfo.FileVersion[0]) + '.' + IntToStr(VerInfo.FixedInfo.FileVersion[1]) + '.' + IntToStr(VerInfo.FixedInfo.FileVersion[2]) + '.' + IntToStr(VerInfo.FixedInfo.FileVersion[3]);
   VerInfo.Free();
end;
function ProductVersionAsString(): String;
var
   VerInfo: TVersionInfo;
begin
   VerInfo := TVersionInfo.Create();
   VerInfo.Load(HINSTANCE);
   Result := IntToStr(VerInfo.FixedInfo.ProductVersion[0]) + '.' + IntToStr(VerInfo.FixedInfo.ProductVersion[1]) + '.' + IntToStr(VerInfo.FixedInfo.ProductVersion[2]) + '.' + IntToStr(VerInfo.FixedInfo.ProductVersion[3]);
   VerInfo.Free();
end;

end.

Thanks Christian!


ReplyQuote

Like what you see and you'd like to help out? 

The best way to help is of course by assisting others with their questions here in the forum, but you can also help us out in other ways:

- Do your shopping at Amazon, it will not cost you anything extra but may generate a small commission for us,
- send a cup of coffee through PayPal ($5, $10, $20, or custom amount),
- become a Patreon,
- donate BitCoin (BTC), or BitCoinCash (BCH).

Share: