: : : Hi,
: : :
: : : In the project menu under options there is a tab version info where you can set the version and revision numbers for your application.
: : :
: : : Question:
: : : How can I read these values from within my application, so that I can create an about box that is so smart that it knows the versionnumber himself and I won't have to change this everytime I increment the versionnumber... I'd like to only change it in the verion info tab and let the about box look there for the current versionnumber. How do I do this ?
: : :
: : :
: : :
: : :

: : : -mac-
: : : mailto:mac_doggie@hotmail.com
: : : the Netherlands...
: : :
: : :
: : Here is a unit, which defines a new TIniFile to read the version info. The ReadString() contains various predefined Idents for various values. All other values names are simply taken as Idents.
: :
: : unit VersionInfo;
: :
: : interface
: :
: : uses
: : SysUtils, Classes, Windows, IniFiles;
: :
: : type
: : TVersionIniFile = class(TCustomIniFile)
: : private
: : FRezBuffer: string;
: : FTransTable: PLongint;
: : FHandle: DWord;
: : FSize: Integer;
: : FFixedFileInfoBuf: PVSFixedFileInfo;
: : FVersionInfoFound: boolean;
: : protected
: : function GetFileVersion: string;
: : function GetFileOS: string;
: : function GetFileType: string;
: : function GetFileLang: string;
: : public
: : constructor Create;
: : procedure Initialize(Filename: string);
: : function ReadString(const Section, Ident, Default: string): string; override;
: : procedure WriteString(const Section, Ident, Value: string); override;
: : procedure ReadSection(const Section: string; Strings: TStrings); override;
: : procedure ReadSections(Strings: TStrings); override;
: : procedure ReadSectionValues(const Section: string; Strings: TStrings); override;
: : procedure EraseSection(const Section: string); override;
: : procedure DeleteKey(const Section, Ident: string); override;
: : procedure UpdateFile; override;
: : end;
: :
: : implementation
: :
: : { TVersionIniFile }
: :
: : const
: : // strings that must be fed to VerQueryValue() function
: : FormatStr = '%s%.4x%.4x\%s%s';
: : SFInfo = '\StringFileInfo\';
: : VerTranslation: PChar = '\VarFileInfo\Translation';
: :
: : constructor TVersionIniFile.Create();
: : begin
: : inherited Create('');
: : end;
: :
: : procedure TVersionIniFile.DeleteKey(const Section, Ident: string);
: : begin
: : end;
: :
: : procedure TVersionIniFile.EraseSection(const Section: string);
: : begin
: : end;
: :
: : function TVersionIniFile.GetFileLang: string;
: : var
: : a: array[0..1023] of char;
: : begin
: : if VerLanguageName(LoWord(FTransTable^), @a, 1023) = 0 then
: : Result := 'Unknown'
: : else
: : Result := a;
: : end;
: :
: : function TVersionIniFile.GetFileOS: string;
: : begin
: : case FFixedFileInfoBuf^.dwFileOS of
: : VOS_UNKNOWN: Result := 'Unknown';
: : VOS_DOS: Result := 'MS-DOS';
: : VOS_OS216: Result := '16-bit OS/2';
: : VOS_OS232: Result := '32-bit OS/2';
: : VOS_NT: Result := 'Windows NT';
: : VOS__WINDOWS16: Result := '16-bit Windows';
: : VOS__PM16: Result := '16-bit PM';
: : VOS__PM32: Result := '32-bit PM';
: : VOS__WINDOWS32: Result := '32-bit Windows';
: : VOS_DOS_WINDOWS16: Result := '16-bit Windows, running on MS-DOS';
: : VOS_DOS_WINDOWS32: Result := 'Win32 API, running on MS-DOS';
: : VOS_OS216_PM16: Result := '16-bit PM, running on 16-bit OS/2';
: : VOS_OS232_PM32: Result := '32-bit PM, running on 32-bit OS/2';
: : VOS_NT_WINDOWS32: Result := 'Win32 API, running on Windows/NT';
: : else Result := 'Unknown';
: : end;
: : end;
: :
: : function VersionString(Ms, Ls: Longint): String;
: : begin
: : Result := Format('%d.%d.%d.%d', [HIWORD(Ms), LOWORD(Ms),
: : HIWORD(Ls), LOWORD(Ls)]);
: : end;
: :
: : function TVersionIniFile.GetFileType: string;
: : begin
: : with FFixedFileInfoBuf^ do
: : Result := Format('%d:%d', [dwFileType, dwFileSubtype]);
: : end;
: :
: : function TVersionIniFile.GetFileVersion: string;
: : begin
: : with FFixedFileInfoBuf^ do
: : Result := VersionString(dwFileVersionMS, dwFileVersionLS);
: : end;
: :
: : procedure TVersionIniFile.Initialize(Filename: string);
: : var
: : SBSize: UInt;
: : Size: Cardinal;
: : begin
: : if Filename <> '' then
: : begin
: : // Determine size of version information
: : FSize := GetFileVersionInfoSize(PChar(Filename), FHandle);
: : FVersionInfoFound := FSize > 0;
: : if not FVersionInfoFound then Exit;
: : // Set the length accordingly
: : SetLength(FRezBuffer, FSize);
: : // Fill the buffer with version information, raise exception on error
: : if not GetFileVersionInfo(PChar(Filename), FHandle, FSize,
: : PChar(FRezBuffer)) then
: : FVersionInfoFound := false;
: : if not FVersionInfoFound then Exit;
: : if not VerQueryValue(PChar(FRezBuffer), VerTranslation,
: : pointer(FTransTable), SBSize) then
: : FVersionInfoFound := false;
: : if not FVersionInfoFound then Exit;
: : if VerQueryValue(PChar(FRezBuffer), '\', Pointer(FFixedFileInfoBuf), Size) then begin
: : if Size < SizeOf(TVSFixedFileInfo) then
: : FVersionInfoFound := false;
: : end;
: : end else
: : FVersionInfoFound := false;
: : end;
: :
: : procedure TVersionIniFile.ReadSection(const Section: string;
: : Strings: TStrings);
: : begin
: : end;
: :
: : procedure TVersionIniFile.ReadSections(Strings: TStrings);
: : begin
: : end;
: :
: : procedure TVersionIniFile.ReadSectionValues(const Section: string;
: : Strings: TStrings);
: : begin
: : end;
: :
: : function TVersionIniFile.ReadString(const Section, Ident,
: : Default: string): string;
: : var
: : P: Pchar;
: : S: UInt;
: : begin
: : if not FVersionInfoFound then Result := ''
: : else if Ident = 'FileVersion' then Result := GetFileVersion
: : else if Ident = 'FileOS' then Result := GetFileOS
: : else if Ident = 'FileType' then Result := GetFileType
: : else if Ident = 'FileLangID' then Result := IntToStr(LoWord(FTransTable^))
: : else if Ident = 'FileLanguage' then Result := GetFileLang
: : else begin
: : Result := Format(FormatStr, [SfInfo, LoWord(FTransTable^),
: : HiWord(FTransTable^), Ident, #0]);
: : // get and return version query info, return empty string on error
: : if VerQueryValue(PChar(FRezBuffer), @Result[1], Pointer(P), S) then
: : Result := StrPas(P)
: : else
: : Result := '';
: : end;
: : end;
: :
: : procedure TVersionIniFile.UpdateFile;
: : begin
: : end;
: :
: : procedure TVersionIniFile.WriteString(const Section, Ident, Value: string);
: : begin
: : end;
: :
: : end.
: :
: :
:
:
: JES*S I'm a rookie... Isn't there anything simpler ? I just thought of something like:
:
:
: iVersion := Application.Version;
: iRevision := Application.Revision;
:
:
:
:

: -mac-
: mailto:mac_doggie@hotmail.com
: the Netherlands...
:
:
:
No. Because the version number isn't stored in the TApplication, but in the version resource. To get the version resource you need to run the code in the TVersionIniFile.Initialize() method. I've created this object for myself, so I could much easier access all that data. It is very simple to use:
var
VersionData: TVersionIniFile;
begin
VersionData := Create; // Create the object
VersionData.Initialize(Application.Exename); // Get the Version Resource
Label1.Caption := VersionData.ReadString('', 'ProductName', ''); // Get the productname (from Project Options)
Label2.Caption := VersionData.ReadString('', 'FileVersion', ''); // Get the File version (from Project Options)
Label3.Caption := VersionData.ReadString('', 'ProductVersion', ''); // Get the ProductVersion (from Project Options)
VersionData.Free; // Destroy the object again
end;
I've created this as part of a much larger object, which uses all kinds of TCustomIniFile descendants to get various different data about the program and its modules. That's why this object is based on that object and not on the TObject. All you really need is the Create(), Initialize(), ReadString(), and Free() methods (as shown in the example). You can get all the Keys from the Project Options by duplicating its name in the call to ReadString().