Recent

Author Topic: Get and use the Build Number within your program  (Read 17830 times)

IPguy

  • Sr. Member
  • ****
  • Posts: 385
Get and use the Build Number within your program
« on: March 16, 2011, 02:55:44 am »
Now that the build number incrementing works (as of 29845 - Paul, thank you),
Here is how I get and use the build number.

Background: this snippet is from my FormCreate event for my main window.  I'm using an internal version number via the variable (duh) "ver".
(Win32-Vista, 0.9.31-29846, 2.4.2)

Add the following to your uses statement:
vinfo, versiontypes

You will also need to download and save the following as vinfo.pas in your program working directory:
http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20100723/8db6b97e/attachment.ksh


Code: [Select]
procedure TfMain.FormCreate(Sender: TObject);
// initialize a bunch of stuff for this app when the form is first opened

     // [0] = Major version, [1] = Minor ver, [3] = Revision, [4] = Build Number
     // The above values can be found in the menu: Project > Project Options > Version Info

Var
  BuildNum : String;
  Info: TVersionInfo;
begin
  Info := TVersionInfo.Create;
  Info.Load(HINSTANCE);
  // grab just the Build Number
  BuildNum := IntToStr(Info.FixedInfo.FileVersion[3]);
  Info.Free;

  // Update the title string - include the version & ver #
  fMain.Caption := sProgName + ', ' + Version + ' Version   v' + ver + '-'+BuildNum;
                                                 

Credits:
Paul Ishenin - for the vinfo.pas unit and the code.
Here is his original post: 
http://webcache.googleusercontent.com/search?q=cache:rPxJJCbpw1wJ:lists.lazarus.freepascal.org/pipermail/lazarus/2010-July/054335.html+lazaarus+get+build+number&cd=2&hl=en&ct=clnk&gl=us&client=firefox-a&source=www.google.com

IPguy

  • Sr. Member
  • ****
  • Posts: 385
Re: Get and use the Build Number within your program
« Reply #1 on: July 15, 2011, 03:44:17 am »
Update:
For the code I show above, I am not using "versiontypes" in my Uses clause.

CaptBill

  • Sr. Member
  • ****
  • Posts: 435
Re: Get and use the Build Number within your program
« Reply #2 on: July 15, 2011, 04:11:45 am »
This would be good to save in the code template feature of Lazarus. Now I got to figure out the right way. Seems to be several.

Should I use the CodeTools define editor?
Or is the best way with a code completion script?

totya

  • Hero Member
  • *****
  • Posts: 577
Re: Get and use the Build Number within your program
« Reply #3 on: May 28, 2012, 04:00:50 am »
Update:
For the code I show above, I am not using "versiontypes" in my Uses clause.

Hi, and this is wrong:
Code: [Select]
[0] = Major version, [1] = Minor ver, [3] = Revision, [4] = Build Number
good version:
Code: [Select]
[0] = Major version, [1] = Minor ver, [2] = Revision, [3] = Build Number
Thanks.

picstart

  • Full Member
  • ***
  • Posts: 236
Re: Get and use the Build Number within your program
« Reply #4 on: May 28, 2012, 04:26:18 pm »
FYI issue with the code win7  pro 32 bit  lazarus v0.9.30.4

Code: [Select]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, vinfo,windows;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);

      // [0] = Major version, [1] = Minor ver, [2] = Revision, [3] = Build Number
     // The above values can be found in the menu: Project > Project Options > Version Info

Var
  BuildNum : String;
  ver, Version:string;
  sProgName:string;
  Info: TVersionInfo;
begin
  Info := TVersionInfo.Create;
  Info.Load(HINSTANCE);
  // grab just the Build Number
  BuildNum := IntToStr(Info.FixedInfo.FileVersion[3]);
  sProgName :='this program';
  ver := IntToStr(Info.FixedInfo.FileVersion[0]);
  Version:=IntToStr(Info.FixedInfo.FileVersion[1]);
  Info.Free;

  // Update the title string - include the version & ver #
 // fMain.Caption := sProgName + ', ' + Version + ' Version   v' + ver + '-'+BuildNum;
 edit1.text:=sProgName + ', ' + Version + ' Version   v' + ver + '-'+BuildNum;
end;

end.
the above code bombs in vinfo on this line
Stream := TResourceStream.CreateFromID(Instance, 1, PChar(RT_VERSION));   

eny

  • Hero Member
  • *****
  • Posts: 1587
Re: Get and use the Build Number within your program
« Reply #5 on: May 28, 2012, 06:27:09 pm »
If you go through the trouble of creating a wrapper like this, you should add 4 more properties/functions to the TVersionInfo class:
- MajorVersion
- MinorVersion
- Revision
- Build
and nót access the bytes Info.FixedInfo.FileVersion[xxx] directly.

If the bytes change for whatever reason, you'll have to change all your programs to access a different byte for the build number.
If you add the above properties, you only have to change the TVersionInfo class to access the correct byte(s).

All posts based on: Win10 (Win64); Lazarus 1.8.0 'stable' (#56594 win64) unless specified otherwise...

totya

  • Hero Member
  • *****
  • Posts: 577
Re: Get and use the Build Number within your program
« Reply #6 on: May 28, 2012, 07:24:29 pm »
FYI issue with the code win7  pro 32 bit  lazarus v0.9.30.4

Code: [Select]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, vinfo,windows;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);

      // [0] = Major version, [1] = Minor ver, [2] = Revision, [3] = Build Number
     // The above values can be found in the menu: Project > Project Options > Version Info

Var
  BuildNum : String;
  ver, Version:string;
  sProgName:string;
  Info: TVersionInfo;
begin
  Info := TVersionInfo.Create;
  Info.Load(HINSTANCE);
  // grab just the Build Number
  BuildNum := IntToStr(Info.FixedInfo.FileVersion[3]);
  sProgName :='this program';
  ver := IntToStr(Info.FixedInfo.FileVersion[0]);
  Version:=IntToStr(Info.FixedInfo.FileVersion[1]);
  Info.Free;

  // Update the title string - include the version & ver #
 // fMain.Caption := sProgName + ', ' + Version + ' Version   v' + ver + '-'+BuildNum;
 edit1.text:=sProgName + ', ' + Version + ' Version   v' + ver + '-'+BuildNum;
end;

end.
the above code bombs in vinfo on this line
Stream := TResourceStream.CreateFromID(Instance, 1, PChar(RT_VERSION));

Hi!

What is the problem with this code?

picstart

  • Full Member
  • ***
  • Posts: 236
Re: Get and use the Build Number within your program
« Reply #7 on: May 29, 2012, 02:13:08 am »
yotya
The code in my earlier post compiles but bombs when running  in vinfo on this line according to the debugger
Stream := TResourceStream.CreateFromID(Instance, 1, PChar(RT_VERSION));   

totya

  • Hero Member
  • *****
  • Posts: 577
Re: Get and use the Build Number within your program
« Reply #8 on: May 29, 2012, 02:54:20 am »
Hi!

This code compile and running for me without problem:

Code: [Select]
constructor TApplicationVersionInfo.Create;
begin
  Inherited;

  Info := TVersionInfo.Create;
  try
    Info.Load(HINSTANCE);

    FMajorVersion    :=Info.FixedInfo.FileVersion[0];
    FMinorVersion    :=Info.FixedInfo.FileVersion[1];
    FRevision        :=Info.FixedInfo.FileVersion[2];
    FBuildNumber     :=Info.FixedInfo.FileVersion[3];

    FMajorVersionStr :=IntToStr(Info.FixedInfo.FileVersion[0]);
    FMinorVersionStr :=IntToStr(Info.FixedInfo.FileVersion[1]);
    FRevisionStr     :=IntToStr(Info.FixedInfo.FileVersion[2]);
    FBuildNumberStr  :=IntToStr(Info.FixedInfo.FileVersion[3]);

    FVersionStr:=
      MajorVersionStr+'.'+
      MinorVersionStr+'.'+
      RevisionStr+' (build'+
      BuildNumberStr+')';

  finally
    if Assigned(Info) then Info.Free;
  end;
end;                             

Perhaps I don't know exactly, what this is mean:
Quote
bombs when running  in vinfo on this line according to the debugger
I think this is mean, when your code is running, crashed when uses vinfo. For me no problem.

Win7x64, lazarus v0.9.30.4 x86

kris

  • Jr. Member
  • **
  • Posts: 59
Re: Get and use the Build Number within your program
« Reply #9 on: June 20, 2014, 08:40:47 am »
Please feel free to use and share, usage examples included in the source (Written and tested on Ubuntu 12.04):

Code: [Select]
{******************************************************************************
 Project : libBinRes
 Version : 0.9 aka "Lite", that only includes one class, namely TAppVersionInfo
 Description: Freepascal library for working with resources compiled into
              executables in Lazarus. Written and tested on Ubuntu 12.04.
 Copyright (c) 2014, Krzysztof Kamil Jacewicz. All rights reserved.
 Contact: k.k.jacewicz@gmail.com

| Redistribution and use in source and binary forms, with or without           |
| modification, are permitted provided that the following conditions are met:  |
|                                                                              |
| Redistributions of source code must retain the above copyright notice, this  |
| list of conditions and the following disclaimer.                             |
|                                                                              |
| Redistributions in binary form must reproduce the above copyright notice,    |
| this list of conditions and the following disclaimer in the documentation    |
| and/or other materials provided with the distribution.                       |
|                                                                              |
| The name of Krzysztof Kamil Jacewicz  may not be used to endorse or promote  |
| products derived from this software without specific prior written           |
| permission.                                                                  |
|                                                                              |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"  |
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE    |
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE   |
| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR  |
| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL       |
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR   |
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER   |
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT           |
| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY    |
| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH  |
| DAMAGE.                                                                      |
|==============================================================================|
| The Developer of this code is Krzysztof Kamil Jacewicz (Poland).             |
| The code is Copyright (c) 1999-2010.                                         |
| All Rights Reserved.                                                         |
|==============================================================================|
| Contributor(s):                                                              |
|==============================================================================|
|                            |
|          (Found at URL: http://www.ararat.cz/synapse/)                       |
|==============================================================================

 ******************************************************************************}

Unit libBinRes;
{$mode objfpc}{$H+}
interface
uses
  Classes, SysUtils, Resource,
  VersionResource, VersionTypes;

Const
  C_DEF_VER_FORMAT             = '{mjr}.{mnr}.{rev}.{bld}';

{******************************************************************************
 USER'S MANUAL:

 Table of content:
       1. Simplest use
       2. Formatted output
       3. Accessing version numbers as integers
       4. About formatting
       5. Advanced


 1. Simplest use:
    (...)
    uses (...), libBinRes;
    (...)
    //something like "1.0.0.0"
      ShowMessage(libBinRes.AppVersionInfo.VersionStr);
    (...)

 2. Formatted output:
    (...)
    uses (...), libBinRes;
    (...)
    //something like "v1.0, rev.0 build 0"
      ShowMessage(libBinRes.AppVersionInfo.VersionStrEx['v{mjr}.{mnr}, rev.{rev} build {bld}']);
    (...)

 3. Accessing version numbers as integers:
    (...)
    uses (...), libBinRes;
    (...)
    var
      minor,major,revision,build_no : integer;
    (...)
      major    := libBinRes.AppVersionInfo.Major;
      minor    := libBinRes.AppVersionInfo.Minor;
      revision := libBinRes.AppVersionInfo.Revision;
      build_no := libBinRes.AppVersionInfo.BuildNo;
    (...)

 4. About formatting
    The VersionStrEx property can format the string with version numbers following
    developer's liking. The Property takes a string as an argument, then substitutes:
    - every "{mjr}" substring with a number of major version,
    - every "{mnr}" substring with a number of minor version,
    - every "{rev}" substring with a revision number,
    - every "{bld}" substring with a build number
    If the passed string is an empty string, then the default formatting will be
    applied, as defined in the C_DEF_VER_FORMAT constant, which is used when calling
    the VersionStr Property.

 5. Advanced
    the libBinRes.AppVersionInfo is a function returning an instance of TAppVersionInfo class.
    The instance is only being created at run-time when first accessed. Means, if you
    do add libBinRes unit to your "uses" clause, but never actually call libBinRes.VersionInf,
    then the instance will never be created.
    The unit will automatically free the instance at the end of your program execution
    (at unloading of the library, from "Finalize" section), if off course, there
    is any instance to be freed.
    Alternatively, you could choose to create your own instance of the TAppVersionInfo
    class and call your object explicitely, then free it explicitely when no more needed.

 ******************************************************************************}

type
  { TAppVersionInfo }

  TAppVersionInfo = class
  private
    FProvidedHinstance : THandle;
    FMajor             : integer;
    FMinor             : integer;
    FRevision          : integer;
    FBuildNo           : integer;
    Function  GetMajorAsStr: string;
    Function  GetMinorAsStr: string;
    Function  GetRevisionAsStr: string;
    Function  GetBuildNoAsStr: string;
    Function  GetVersionStr: string;
    Function  GetVersionStrEx(ver_format: string): string;
  public
    Constructor Create; overload;
    Constructor Create(const AProvidedHinstance : THandle); overload;
    Procedure Reload;
    Property Major: integer read FMajor;
    Property Minor: integer read FMinor;
    Property Revision: integer read FRevision;
    Property BuildNo: integer read FBuildNo;
    Property MajorAsStr: string read GetMajorAsStr;
    Property MinorAsStr: string read GetMinorAsStr;
    Property RevisionAsStr: string read GetRevisionAsStr;
    Property BuildNoAsStr: string read GetBuildNoAsStr;
    Property VersionStr: string read GetVersionStr;
    Property VersionStrEx[ver_format: string]: string read GetVersionStrEx; default;
  end;

Function AppVersionInfo: TAppVersionInfo;

implementation
Var
  FVersionInfo                   : TAppVersionInfo = nil;

Function AppVersionInfo: TAppVersionInfo;
 begin
   if not Assigned(FVersionInfo)then FVersionInfo := TAppVersionInfo.Create;
   Result := FVersionInfo;
 end;

{ TAppVersionInfo }

Constructor TAppVersionInfo.Create;
 begin
   inherited Create;
   FProvidedHInstance := -1;
   Reload;
 end;

Constructor TAppVersionInfo.Create(const AProvidedHinstance : THandle); overload;
 begin
   inherited Create;
   FProvidedHInstance := AProvidedHinstance;
   Reload;
 end;

Procedure TAppVersionInfo.Reload;
 var
   AVersionResource   : TVersionResource;
   AResourceStream    : TResourceStream;
 begin
 //Allocate resources, and load data:
   AVersionResource := TVersionResource.Create;
   if not Assigned(AVersionResource)then exit;
   Try
     if(FProvidedHInstance<0)
       then AResourceStream := TResourceStream.CreateFromID(HINSTANCE, 1, PChar(RT_VERSION))
       else AResourceStream := TResourceStream.CreateFromID(FProvidedHInstance, 1, PChar(RT_VERSION));
     if Assigned(AResourceStream)then
        try
          AVersionResource.SetCustomRawDataStream(AResourceStream);
          with AVersionResource.FixedInfo do
            begin
             FMajor    := FileVersion[0];
             FMinor    := FileVersion[1];
             FRevision := FileVersion[2];
             FBuildNo  := FileVersion[3];
            end;
          AVersionResource.SetCustomRawDataStream(nil);
        finally
          FreeAndNil(AResourceStream);
        end;
   Finally
   //Free resources:
     FreeAndNil(AVersionResource);
   End;
 end;

Function TAppVersionInfo.GetMajorAsStr: string;
         begin Result := IntToStr(Major); end;

Function TAppVersionInfo.GetMinorAsStr: string;
         begin Result := IntToStr(Minor); end;

Function TAppVersionInfo.GetRevisionAsStr: string;
         begin Result := IntToStr(Revision); end;

Function TAppVersionInfo.GetBuildNoAsStr: string;
         begin Result := IntToStr(BuildNo); end;

Function TAppVersionInfo.GetVersionStr: string;
         begin Result := VersionStrEx[C_DEF_VER_FORMAT]; end;

Function TAppVersionInfo.GetVersionStrEx(ver_format: string): string;
          begin
            if(ver_format='')then ver_format:=C_DEF_VER_FORMAT;
            Result := StringReplace(ver_format,'{mjr}',MajorAsStr,[rfReplaceAll]);
            Result := StringReplace(Result    ,'{mnr}',MinorAsStr,[rfReplaceAll]);
            Result := StringReplace(Result    ,'{rev}',RevisionAsStr,[rfReplaceAll]);
            Result := StringReplace(Result    ,'{bld}',BuildNoAsStr,[rfReplaceAll]);
          end;

Finalization
 if Assigned(FVersionInfo)then FreeAndNil(FVersionInfo);
end.

Best Regards,
Kris