Solved

How do I get the VersionInfo for my program from within my program?

Posted on 2001-07-02
13
417 Views
Last Modified: 2010-04-06
I want to show the fileversion number in my about box.

How do I get the FileVersion string that is defined within my project|Options|Version Info dialog?

Ideally, I don't want to have to re-open the application from disk.

I simply want to extract it from the current program.

Regards,

Richard Quadling.
0
Comment
Question by:RQuadling
  • 5
  • 2
  • 2
  • +3
13 Comments
 
LVL 13

Expert Comment

by:Epsylon
Comment Utility
0
 
LVL 40

Author Comment

by:RQuadling
Comment Utility
From this, can I surmise that the versioninfo is not available to the current program - I have to open the program twice to get the info?

Is it not held as a resource in the current application (I've been reading! Probably the wrong thing, but ... ;-) ).


Regards,

Richard Quadling.
0
 
LVL 2

Expert Comment

by:FrodoBeggins
Comment Utility
You can use GetFileVersionInfo and VerQueryValue functions. Or use any kind of component - like TVersionInfo from the RX Components Suite
0
 
LVL 1

Expert Comment

by:bozo7
Comment Utility
I use the following function

function GetProgramVersion(path : string) : string;
var
   nZero,nSize : cardinal;
   lpData      : pointer;
   p           : pointer;
begin
 result:='Unknown';
 nSize:=GetFileVersionInfoSize(pchar(path),nZero);
 if nSize>0 then
  begin
   getmem(lpData,nSize);
   if GetFileVersionInfo(pchar(path),0,nSize,lpData) then
    if VerQueryValue(lpData,'\',p,nZero) then
     begin
     result:=inttostr(tVSFIXEDFILEINFO(p^).dwFileVersionMS shr 16)+'.'+
             inttostr(tVSFIXEDFILEINFO(p^).dwFileVersionMS and $FFFF)+'.'+
             inttostr(tVSFIXEDFILEINFO(p^).dwFileVersionLS shr 16)+'.'+
             inttostr(tVSFIXEDFILEINFO(p^).dwFileVersionLS and $FFFF);
     end;
   freemem(lpData,nSize);
  end;
end;


Then I call it like this

version.caption := 'Release '+GetProgramVersion(application.exename);

I don't remember who gave me this function, but I got it on EE somehwhere. It works well though.

Ross
0
 
LVL 1

Expert Comment

by:bozo7
Comment Utility
version.caption referenced above. Version is a TLabel.

Ross
0
 
LVL 2

Accepted Solution

by:
Felixin earned 50 total points
Comment Utility
What about this unit ?

START
-----------------------------------------------------------
unit rpVersionInfo;
//version 1.0 3/8/98 written and tested with Delphi 3.

(*Written by Rick Peterson, this component is released to the public domain for
  any type of use, private or commercial.  Should you enhance the product
  please give me credit and send me a copy.  Also please report any bugs to me.
  Send all coorespondence to rickpet@airmail.net. *)

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  TypInfo;

type
{$M+}
(* Have you seen the $M+ before???This tells delphi to publish RTTI info for
   enumerated types.  Basically allowing your enumerated types to act as
   strings with GetEnumName *)
  TVersionType=(vtCompanyName, vtFileDescription, vtFileVersion, vtInternalName,
                vtLegalCopyright,vtLegalTradeMark, vtOriginalFileName,
                vtProductName, vtProductVersion, vtComments);
{$M-}
  TrpVersionInfo = class(TComponent)
(* This component will allow you to get Version Info from your program at
   RunTime *)
  private
    FVersionInfo : Array [0 .. ord(high(TVersionType))] of string;
  protected
    function GetCompanyName: string;
    function GetFileDescription: string;
    function GetFileVersion: string;
    function GetInternalName: string;
    function GetLegalCopyright: string;
    function GetLegalTradeMark: string;
    function GetOriginalFileName: string;
    function GetProductName: string;
    function GetProductVersion: string;
    function GetComments: string;
    function GetVersionInfo(VersionType: TVersionType): string; virtual;
    procedure SetVersionInfo; virtual;
  public
    constructor Create(AOwner: TComponent); override;
  published
(* Label1.Caption := VersionInfo1.FileVersion;  Simple as that.
   NOTE:  ALL the properties are READONLY so you can not view them with the
   Object Inspector *)
    property CompanyName: string read GetCompanyName;
    property FileDescription: string read GetFileDescription;
    property FileVersion: string read GetFileVersion;
    property InternalName: string read GetInternalName;
    property LegalCopyright: string read GetLegalCopyright;
    property LegalTradeMark: string read GetLegalTradeMark;
    property OriginalFileName: string read GetOriginalFileName;
    property ProductName: string read GetProductName;
    property ProductVersion: string read GetProductVersion;
    property Comments: string read GetComments;
  end;

var
  VersionInfo : TrpVersionInfo;

procedure Register;

implementation

const
  RootInfo = 'StringFileInfo\040A04E4\';

constructor TrpVersionInfo.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  SetVersionInfo;
end;

function TrpVersionInfo.GetCompanyName: string;
begin
  result := GeTVersionInfo(vtCompanyName);
end;

function TrpVersionInfo.GetFileDescription: string;
begin
  result := GeTVersionInfo(vtFileDescription);
end;

function TrpVersionInfo.GetFileVersion: string;
begin
  result := GeTVersionInfo(vtFileVersion);
end;

function TrpVersionInfo.GetInternalName: string;
begin
  result := GeTVersionInfo(vtInternalName);
end;

function TrpVersionInfo.GetLegalCopyright: string;
begin
  result := GeTVersionInfo(vtLegalCopyright);
end;

function TrpVersionInfo.GetLegalTradeMark: string;
begin
  result := GeTVersionInfo(vtLegalTradeMark);
end;

function TrpVersionInfo.GetOriginalFileName: string;
begin
  result := GeTVersionInfo(vtOriginalFileName);
end;

function TrpVersionInfo.GetProductName: string;
begin
  result := GeTVersionInfo(vtProductName);
end;

function TrpVersionInfo.GetProductVersion: string;
begin
  result := GeTVersionInfo(vtProductVersion);
end;

function TrpVersionInfo.GetComments: string;
begin
  result := GeTVersionInfo(vtComments);
end;

function TrpVersionInfo.GeTVersionInfo(VersionType: TVersionType): string;
begin
  result := FVersionInfo[ord(VersionType)];
end;

procedure TrpVersionInfo.SeTVersionInfo;
var
  sAppName,sVersionType : string;
  iAppSize, iLenOfValue : DWord;
  i: integer;
  pcBuf,pcValue, Key: PChar;
begin
  sAppName := Application.ExeName;
  iAppSize:= GetFileVersionInfoSize(PChar(sAppName),iAppSize);
  if (iAppSize > 0) then
  begin
    pcBuf := AllocMem(iAppSize);
    GetFileVersionInfo(PChar(sAppName),0,iAppSize,pcBuf);
    for i := 0 to Ord(High(TVersionType)) do
    begin
      sVersionType := GetEnumName(TypeInfo(TVersionType),i);
      sVersionType := Copy(sVersionType,3,length(sVersionType));
      Key := PChar (RootInfo + sVersionType);
      if VerQueryValue(pcBuf, Key, Pointer(pcValue),iLenOfValue) then
        FVersionInfo[i] := pcValue;
    end;
    FreeMem(pcBuf,iAppSize);
  end;
end;                            

procedure Register;
begin
  RegisterComponents('FreeWare', [TrpVersionInfo]);
end;

initialization
  VersionInfo := TrpVersionInfo.Create (nil);

finalization
  VersionInfo.Free;

end.
-----------------------------------------------------------
END

I don't remember where I got the unit, but please note that I'm not the author.

The author is Rick Peterson.

I've been using this unit in Delphi 5 without problems.

Note also that you acces version information through the properties of te object like this

VersionInfo.ProductVersion;

Greetings

F?lix



0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 40

Author Comment

by:RQuadling
Comment Utility
Initially, I tried the unit above and got nowhere - the values where all blank.

I then tried to use the TResourceStream. Managed to get it loaded into some memory, but can't really work out how to navigate around it.

But I did manage to save it to disk!

Then noticed that there is a slightly different code at the top of the file which relates to the language Locale ID.

The example above uses a locale of $040A = Spanish (Traditional Sort).

I changed it to my language (English - United Kingdom $0809) and all works well.

Thanks.
0
 
LVL 40

Author Comment

by:RQuadling
Comment Utility
Not EXACTLY what I wanted. I didn't want to have to reload the file, but it does what I want and doesn't seem too slow.

Thanks.

NOTE: More points but lower grade.
0
 
LVL 40

Author Comment

by:RQuadling
Comment Utility
The new code (and my change is to the const RootInfo) is ...

------------------------------------------------
unit rpVersionInfo;
//version 1.0 3/8/98 written and tested with Delphi 3.

{Written by Rick Peterson, this component is released to the public domain for
 any type of use, private or commercial.  Should you enhance the product
 please give me credit and send me a copy.  Also please report any bugs to me.
 Send all coorespondence to rickpet@airmail.net. }

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 TypInfo;

type
{$M+}
(* Have you seen the $M+ before???This tells delphi to publish RTTI info for
  enumerated types.  Basically allowing your enumerated types to act as
  strings with GetEnumName *)
 TVersionType=(vtCompanyName, vtFileDescription, vtFileVersion, vtInternalName,
               vtLegalCopyright,vtLegalTradeMark, vtOriginalFileName,
               vtProductName, vtProductVersion, vtComments);
{$M-}
 TrpVersionInfo = class(TComponent)
(* This component will allow you to get Version Info from your program at RunTime *)
 private
   FVersionInfo : Array [0 .. ord(high(TVersionType))] of string;
 protected
   function GetCompanyName: string;
   function GetFileDescription: string;
   function GetFileVersion: string;
   function GetInternalName: string;
   function GetLegalCopyright: string;
   function GetLegalTradeMark: string;
   function GetOriginalFileName: string;
   function GetProductName: string;
   function GetProductVersion: string;
   function GetComments: string;
   function GetVersionInfo(VersionType: TVersionType): string; virtual;
   procedure SetVersionInfo; virtual;
 public
   constructor Create(AOwner: TComponent); override;
 published
(* Label1.Caption := VersionInfo1.FileVersion;  Simple as that.
  NOTE:  ALL the properties are READONLY so you can not view them with the
  Object Inspector *)
   property CompanyName: string read GetCompanyName;
   property FileDescription: string read GetFileDescription;
   property FileVersion: string read GetFileVersion;
   property InternalName: string read GetInternalName;
   property LegalCopyright: string read GetLegalCopyright;
   property LegalTradeMark: string read GetLegalTradeMark;
   property OriginalFileName: string read GetOriginalFileName;
   property ProductName: string read GetProductName;
   property ProductVersion: string read GetProductVersion;
   property Comments: string read GetComments;
 end;

var
 VersionInfo : TrpVersionInfo;

procedure Register;

implementation

const
{
3rd July 2001 - Richard Quadling.
The Language Locale ID that is set in Project|Options relates to the first 4 characters after the first \ in the Root Info.

RootInfo = 'StringFileInfo\040A04E4\'; Spanish - Traditional Sort
}
      RootInfo = 'StringFileInfo\080904E4\'; { English - United Kingdom }

constructor TrpVersionInfo.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 SetVersionInfo;
end;

function TrpVersionInfo.GetCompanyName: string;
begin
 result := GetVersionInfo(vtCompanyName);
end;

function TrpVersionInfo.GetFileDescription: string;
begin
 result := GetVersionInfo(vtFileDescription);
end;

function TrpVersionInfo.GetFileVersion: string;
begin
 result := GetVersionInfo(vtFileVersion);
end;

function TrpVersionInfo.GetInternalName: string;
begin
 result := GetVersionInfo(vtInternalName);
end;

function TrpVersionInfo.GetLegalCopyright: string;
begin
 result := GetVersionInfo(vtLegalCopyright);
end;

function TrpVersionInfo.GetLegalTradeMark: string;
begin
 result := GetVersionInfo(vtLegalTradeMark);
end;

function TrpVersionInfo.GetOriginalFileName: string;
begin
 result := GetVersionInfo(vtOriginalFileName);
end;

function TrpVersionInfo.GetProductName: string;
begin
 result := GetVersionInfo(vtProductName);
end;

function TrpVersionInfo.GetProductVersion: string;
begin
 result := GetVersionInfo(vtProductVersion);
end;

function TrpVersionInfo.GetComments: string;
begin
 result := GetVersionInfo(vtComments);
end;

function TrpVersionInfo.GeTVersionInfo(VersionType: TVersionType): string;
begin
 result := FVersionInfo[ord(VersionType)];
end;

procedure TrpVersionInfo.SeTVersionInfo;
var
 sAppName,sVersionType : string;
 iAppSize, iLenOfValue : DWord;
 i: integer;
 pcBuf,pcValue, Key: PChar;
begin
 sAppName := Application.ExeName;
 iAppSize:= GetFileVersionInfoSize(PChar(sAppName),iAppSize);
 if (iAppSize > 0) then
 begin
      pcBuf := AllocMem(iAppSize);
      GetFileVersionInfo(PChar(sAppName),0,iAppSize,pcBuf);
      for i := 0 to Ord(High(TVersionType)) do
      begin
        sVersionType := GetEnumName(TypeInfo(TVersionType),i);
        sVersionType := Copy(sVersionType,3,length(sVersionType));
        Key := PChar (RootInfo + sVersionType);
        if VerQueryValue(pcBuf, Key, Pointer(pcValue),iLenOfValue) then
            FVersionInfo[i] := pcValue;
      end;
      FreeMem(pcBuf,iAppSize);
 end;
end;

procedure Register;
begin
 RegisterComponents('FreeWare', [TrpVersionInfo]);
end;

initialization
 VersionInfo := TrpVersionInfo.Create (nil);

finalization
 VersionInfo.Free;

end.

0
 
LVL 2

Expert Comment

by:Felixin
Comment Utility
Yes, in fact I have to pass a certain time to realize that the problem was in languaje code.

Sorry, for not mentioning it and thanks for the points.

Felixin
0
 

Expert Comment

by:dicktse
Comment Utility
You don't need to hard-code the language ID. You can get the language ID by using this code:


procedure TrpVersionInfo.SeTVersionInfo;
var
  sAppName,sVersionType : string;
  iAppSize, iLenOfValue : DWord;
  i: integer;
  pcBuf,pcValue, Key: PChar;
  pTranslate : Pointer
  dwLanguage, dwCodePage : DWORD;
begin
  sAppName := Application.ExeName;
  iAppSize:= GetFileVersionInfoSize(PChar(sAppName),iAppSize);
  if (iAppSize > 0) then
  begin
    pcBuf := AllocMem(iAppSize);
    GetFileVersionInfo(PChar(sAppName),0,iAppSize,pcBuf);
    for i := 0 to Ord(High(TVersionType)) do
    begin
      sVersionType := GetEnumName(TypeInfo(TVersionType),i);
      sVersionType := Copy(sVersionType,3,length(sVersionType));
      VerQueryValue(pcBuf, '\VarFileInfo\Translation', pTranslate, iAppSize);
      dwLanguage := LoWord(PInteger(pTranslate)^);
      dwCodePage := HiWord(PInteger(pTranslate)^);
      Key:= PChar(Format('\StringFileInfo\%.8x\' + sVersionType, [(dwLanguage shl 16) or dwCodePage]));
      if VerQueryValue(pcBuf, Key, Pointer(pcValue),iLenOfValue) then
        FVersionInfo[i] := pcValue;
    end;
    FreeMem(pcBuf,iAppSize);
  end;
end;
0
 
LVL 40

Author Comment

by:RQuadling
Comment Utility
Thanks for that. Long time closed question too.
0
 

Expert Comment

by:dicktse
Comment Utility
welcome... i just want to share my knowledge to people who are searching for this topic~
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now