Solved

Gobal Application Wide Variable

Posted on 2004-09-29
5
288 Views
Last Modified: 2010-04-05
I have a variable in a projects DPR that I need access to from the main form.  This variable contains a build number assigned when a tagged build from CVS is done.  How do I get access to this variable, or, is there a better way of doing it?

Thanks,

Stuart.
0
Comment
Question by:SJohnson
  • 2
  • 2
5 Comments
 
LVL 12

Accepted Solution

by:
Lee_Nover earned 125 total points
Comment Utility
have a unit like uVersion.pas and in it this global variable
0
 
LVL 1

Author Comment

by:SJohnson
Comment Utility
Cheers Lee!  You're a legend!
0
 
LVL 17

Expert Comment

by:Wim ten Brink
Comment Utility
Alternate solution for build numbers: create a version resource and store it in there...
Delphi is able to compile *.rc files into *.res files if you add the *.rc file to your project thus you could create a project1.rc file, put a version resource in it like this:
-----------------------------
LANGUAGE LANG_DUTCH,SUBLANG_DUTCH
PROJECT1 VERSIONINFO LOADONCALL MOVEABLE DISCARDABLE IMPURE
FILEVERSION 1, 0, 0, 1
PRODUCTVERSION 1, 0, 0, 1
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
{ BLOCK "StringFileInfo"
  { BLOCK "041304E4"
    { VALUE "CompanyName", "\000"
      VALUE "FileDescription", "\000"
      VALUE "FileVersion", "5.0.0.129\000"
      VALUE "InternalName", "Project1\000"
      VALUE "LegalCopyright", "\000"
      VALUE "LegalTrademarks", "\000"
      VALUE "OriginalFilename", "\000"
      VALUE "ProductName", "\000"
      VALUE "ProductVersion", "1.0.0.1\000"
      VALUE "Comments", "\000"
    }
  }
  BLOCK "VarFileInfo" { VALUE "Translation", 1043, 1252 }
}
-----------------------------
And add this file to your project. Since it's just a text file, you can use notepad or the Delphi editor to open it, modify it and do whatever else you like to do with it.
From the menu, select "Project/Add to project" and just add the *.rc file... (Set 'File of Type' to *.rc)
0
 
LVL 1

Author Comment

by:SJohnson
Comment Utility
Hi Workshop Alex

The resource idea is a good one.  However, all we need is a single tag.  What I was thinking of doing is:

;Add String Table Defines

#define   BUILDTAG     1

;Add String Table

STRINGTABLE DISCARDABLE
BEGIN
    BUILDTAG     "$Name: $"
END

which works very nicely.  However, what we'd ideally like is something like:

BUILDTAG RC_STRING "$Name: $" (or something similar).

Is there any way of doing this?

Cheers.

Stu.
0
 
LVL 17

Expert Comment

by:Wim ten Brink
Comment Utility
Just use:

PROJECT1 VERSIONINFO LOADONCALL MOVEABLE DISCARDABLE IMPURE
FILEVERSION 1, 0, 0, 1
PRODUCTVERSION 1, 0, 0, 1
{ }

As a result, there's a very small version resource now in your project. All it contains is a file version and project version. But if you want more information, you could use the version resource dialog that Delphi offers. It's a bit more useful.

What you actually want, i think, is to read this version information from your executable. Here's a unit that can help you to read it from your application:

unit untVersionInfo;
interface
uses SysUtils, Windows, Dialogs, Classes;
type
  { define a generic exception class for version info, and an exception to indicate that no version info is available. }
  EVerInfoError = class(Exception);
  ENoVerInfoError = class(Exception);
  eNoFixeVerInfo = class(Exception);
  // define enum type representing different types of version info
  TVerInfoType = (viCompanyName, viFileDescription, viFileVersion, viInternalName, viLegalCopyright, viLegalTrademarks, viOriginalFilename, viProductName, viProductVersion, viComments);
const
  // define an array constant of strings representing the pre-defined version information keys.
  VerNameArray: array[TVerInfoType] of string[20] = ('CompanyName', 'FileDescription', 'FileVersion', 'InternalName', 'LegalCopyright', 'LegalTrademarks', 'OriginalFilename', 'ProductName', 'ProductVersion', 'Comments');
type
  TS_VerLangCharSet = record
    Lang: Word;
    CharSet: Word;
  end;
  PS_VerTranslationTable = ^TS_VerTranslationTable;
  TS_VerTranslationTable = array[0..MaxListSize] of TS_VerLangCharSet;
  TVerInfoResource = class
  private
    Handle: DWord;
    Size: Integer;
    RezBuffer: string;
    FTransTable: PInteger;
    FixedFileInfoBuf: PVSFixedFileInfo;
    FFileFlags: TStringList;
    FFileName: TFilename;
    FSucces: Boolean;
    FVerError: string;
    FTransCount: Integer;
    function GetFileType: string;
    function GetTranslations(Index: Integer): string;
  protected
    function GetFileVersion: string;
    function GetProductVersion: string;
    function GetFileOS: string;
  public
    constructor Create(AFileName: TFilename);
    destructor Destroy; override;
    function GetPreDefKeyString(AVerKind: TVerInfoType): string;
    function GetUserDefKeyString(AKey: string): string;
    property Filename: TFilename read FFilename;
    property Succes: Boolean read FSucces;
    property VerError: string read FVerError;
    property FileVersion: string read GetFileVersion;
    property ProductVersion: string read GetProductVersion;
    property FileOS: string read GetFileOS;
    property FileType: string read GetFileType;
    property FileFlags: TStringList read FFileFlags;
    property TransCount: Integer read FTransCount;
    property Translations[Index: Integer]: string read GetTranslations;
  end;
implementation
const
  // strings that must be fed to VerQueryValue() function
  SFInfo = '\StringFileInfo\';
  VerTranslation: PChar = '\VarFileInfo\Translation';
  FormatStr = '%s%.4x%.4x\%s%s';
constructor TVerInfoResource.Create(AFileName: TFilename);
var
  SBSize: UInt;
  ASize: Cardinal;
begin
  FSucces := True;
  FVerError := '';
  FFileName := aFileName;
  FFileFlags := TStringList.Create;
  try
    Size := GetFileVersionInfoSize(PChar(FFileName), Handle);
    if (Size <= 0) then raise ENoVerInfoError.Create('No Version Info Available.');
    SetLength(RezBuffer, Size);
    if not GetFileVersionInfo(PChar(FFileName), Handle, Size, PChar(RezBuffer)) then raise EVerInfoError.Create('Cannot obtain version info.');
    if not VerQueryValue(PChar(RezBuffer), VerTranslation, pointer(FTransTable), SBSize) then raise EVerInfoError.Create('No language info.');
    FTransCount := SBSize div SizeOf(TS_VerLangCharSet);
    if VerQueryValue(PChar(RezBuffer), '\', Pointer(FixedFileInfoBuf), ASize) then begin
      if (ASize < SizeOf(TVSFixedFileInfo)) then raise eNoFixeVerInfo.Create('No fixed file info');
    end
    else begin
      raise eNoFixeVerInfo.Create('No fixed file info');
    end;
    with FixedFileInfoBuf^ do begin
      if (dwFileFlagsMask and dwFileFlags and VS_FF_PRERELEASE) <> 0 then FFileFlags.Add('Pre-release');
      if (dwFileFlagsMask and dwFileFlags and VS_FF_PRIVATEBUILD) <> 0 then FFileFlags.Add('Private build');
      if (dwFileFlagsMask and dwFileFlags and VS_FF_SPECIALBUILD) <> 0 then FFileFlags.Add('Special build');
      if (dwFileFlagsMask and dwFileFlags and VS_FF_DEBUG) <> 0 then FFileFlags.Add('Debug');
    end;
  except
    on E: Exception do begin
      FSucces := False;
      FVerError := E.Message;
    end;
  end;
end;
destructor TVerInfoResource.Destroy;
begin
  FFileFlags.Free;
end;
function TVerInfoResource.GetPreDefKeyString(AVerKind: TVerInfoType): string;
var
  P: PChar;
  S: UInt;
begin
  Result := Format(FormatStr, [SfInfo, LoWord(FTransTable^), HiWord(FTransTable^), VerNameArray[aVerKind], #0]);
  if VerQueryValue(PChar(RezBuffer), @Result[1], Pointer(P), S) then begin
    Result := StrPas(P);
  end
  else begin
    Result := '';
  end;
end;
function TVerInfoResource.GetUserDefKeyString(AKey: string): string;
var
  P: Pchar;
  S: UInt;
begin
  Result := Format(FormatStr, [SfInfo, LoWord(FTransTable^), HiWord(FTransTable^), aKey, #0]);
  if VerQueryValue(PChar(RezBuffer), @Result[1], Pointer(P), S) then begin
    Result := StrPas(P);
  end
  else begin
    Result := '';
  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 TVerInfoResource.GetFileVersion: string;
begin
  with FixedFileInfoBuf^ do begin
    Result := VersionString(dwFileVersionMS, dwFileVersionLS);
  end;
end;
function TVerInfoResource.GetProductVersion: string;
begin
  with FixedFileInfoBuf^ do begin
    Result := VersionString(dwProductVersionMS, dwProductVersionLS);
  end;
end;
function TVerInfoResource.GetFileOS: string;
begin
  with FixedFileInfoBuf^ do begin
    case dwFileOS of
      VOS_UNKNOWN: Result := 'Unknown';
      VOS_DOS: Result := 'Designed for MS-DOS';
      VOS_OS216: Result := 'Designed for 16-bit OS/2';
      VOS_OS232: Result := 'Designed for 32-bit OS/2';
      VOS_NT: Result := 'Designed for Windows NT';
      VOS__WINDOWS16: Result := 'Designed for 16-bit Windows';
      VOS__PM16: Result := 'Designed for 16-bit PM';
      VOS__PM32: Result := 'Designed for 32-bit PM';
      VOS__WINDOWS32: Result := 'Designed for 32-bit Windows';
      VOS_DOS_WINDOWS16: Result := 'Designed for 16-bit Windows, running on MS-DOS';
      VOS_DOS_WINDOWS32: Result := 'Designed for Win32 API, running on MS-DOS';
      VOS_OS216_PM16: Result := 'Designed for 16-bit PM, running on 16-bit OS/2';
      VOS_OS232_PM32: Result := 'Designed for 32-bit PM, running on 32-bit OS/2';
      VOS_NT_WINDOWS32: Result := 'Designed for Win32 API, running on Windows/NT';
      else
        Result := 'Unknown';
    end;
  end;
end;
function TVerInfoResource.GetFileType: string;
begin
  with FixedFileInfoBuf^ do begin
    case dwFileType of
      VFT_UNKNOWN: Result := 'Unknown';
      VFT_APP: Result := 'application';
      VFT_DLL: Result := 'dynamic link library';
      VFT_DRV: Result := 'device driver';
      VFT_Font: Result := 'font';
      VFT_VxD: Result := 'virtual device';
      VFT_STATIC_LIB: Result := 'static-link library';
      else
        Result := 'strange filetype';
    end;
  end;
end;
function TVerInfoResource.GetTranslations(Index: Integer): string;
begin
  with PS_VerTranslationTable(FTransTable)[Index] do
    Result := Format('%4.4x%4.4x', [Lang, CharSet]);
end;
end.

But above code gives you a lot more than just version information, of course. Still, it is very useful if you want to display the build number in your application.
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

771 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

11 Experts available now in Live!

Get 1:1 Help Now