Avatar billede egeskov Nybegynder
02. oktober 2002 - 18:21 Der er 3 kommentarer og
1 løsning

Module Version Number

Hvordan kan jeg fra koden tilgå Module Version Number i mit projekt? Jeg har en AboutBox, som skal vise dette versionsnummer (fx: 0.9.4.30), men jeg glemmer lidt for tit at opdatere AboutBox'en.
Avatar billede borrisholt Novice
02. oktober 2002 - 18:33 #1
unit BorrisholtVerInfo;

interface

uses
  {$IFDEF WIN32}
  Windows, Classes;
  {$ENDIF}

type
  {Record holding version numbers}
  TVersionNumber = record
    V1, V2, V3, V4 : Word;
  end;

  {Record holding fixed file info}
  Tvs_FixedFileInfo = record
    dwSignature : DWORD;
    dwStrucVersion : DWORD;
    dwFileVersionMS : DWORD;
    dwFileVersionLS : DWORD;
    dwProductVersionMS : DWORD;
    dwProductVersionLS : DWORD;
    dwFileFlagsMask : DWORD;
    dwFileFlags : DWORD;
    dwFileOS : DWORD;
    dwFileType : DWORD;
    dwFileSubtype : DWORD;
    dwFileDateMS : DWORD;
    dwFileDateLS : DWORD;
  end;

  {The component class}
  TVersionInfo = class(TComponent)
  private
    FPInfoBuffer : PChar;          {pointer to info buffer}
    FFixedInfo : Tvs_FixedFileInfo; {storage for fixed file info}
    FTransStr : string;            {translation info encoded in string}
    FLanguageCode : Word;          {code number for the language}
    FCharSetCode : Word;            {code number for the char-set}
    {property storage}
    FFileName : string;
    FHaveInfo : Boolean;
    {general private methods}
    procedure GetInfoBuffer(Len : DWORD);
      {Creates an info buffer of required size}
    {property access methods}
    procedure SetFileName(AName : string);
    function GetProductVersionNumber : TVersionNumber;
    function GetFileOS : DWORD;
    function GetFileType : DWORD;
    function GetFileSubType : DWORD;
    function GetFileFlagsMask : DWORD;
    function GetFileFlags : DWORD;
    function GetFileVersionNumber : TVersionNumber;
    function GetLanguage : string;
    function GetCharSet : string;
  protected
    {protected methods}
    procedure ClearProperties; virtual;
      {forces properties to return cleared values}
    procedure ReadVersionInfo; virtual;
      {reads version info from file}
    {property access method}
    function GetStringFileInfo(Index : integer) : string; virtual;
  public
    {class constructor & destructor}
    constructor Create(AOwner : TComponent); override;
    destructor Destroy; override;
    {Properties}
    property HaveInfo : Boolean read FHaveInfo;
      {Property true if file version info for the file per FileName property has
      been successfully read}
    property FileVersionNumber : TVersionNumber read GetFileVersionNumber;
      {Version number of file, in numeric format, from fixed file info}
    property ProductVersionNumber : TVersionNumber read GetProductVersionNumber;
      {Version number of product, in numeric format, from fixed file info}
    property FileOS : DWORD read GetFileOS;
      {Code describing operating system to be used by file}
    property FileType : DWORD read GetFileType;
      {Code descibing type of file}
    property FileSubType : DWORD read GetFileSubType;
      {Code describing sub-type of file - only used for certain values of
      FileType property}
    property FileFlagsMask : DWORD read GetFileFlagsMask;
      {Code describing which FileFlags are valid}
    property FileFlags : DWORD read GetFileFlags;
      {Flags describing file state}
    property Comments : string  index 0 read GetStringFileInfo;
      {String file info property giving user defined comments}
    property CompanyName : string index 1 read GetStringFileInfo;
      {String file info property giving name of company}
    property FileDescription : string index 2 read GetStringFileInfo;
      {String file info property giving description of file}
    property FileVersion : string index 3 read GetStringFileInfo;
      {String file info property giving version number of file in string format}
    property InternalName : string index 4 read GetStringFileInfo;
      {String file info property giving internal name of file}
    property LegalCopyright : string index 5 read GetStringFileInfo;
      {String file info property giving copyright message}
    property LegalTrademarks : string index 6 read GetStringFileInfo;
      {String file info property giving trademark info}
    property OriginalFileName : string index 7 read GetStringFileInfo;
      {String file info property giving original name of file}
    property PrivateBuild : string index 8 read GetStringFileInfo;
      {String file info property giving information about a private build of
      file}
    property ProductName : string index 9 read GetStringFileInfo;
      {String file info property giving name of product}
    property ProductVersion : string index 10 read GetStringFileInfo;
      {String file info property giving version number of product in string
      format}
    property SpecialBuild : string index 11 read GetStringFileInfo;
      {String file info property giving information about a special build of
      file}
    property Language : string read GetLanguage;
      {Name of language in use}
    property CharSet : string read GetCharSet;
      {Name of character set in use}
  published
    property FileName : string read FFileName write SetFileName;
      {Name of file to which version information relates}
  end;

procedure Register;

implementation

uses
  SysUtils, Forms;

{ --- Public methods for class --- }

constructor TVersionInfo.Create(AOwner : TComponent);
  {Class constructor}
begin
  inherited Create(AOwner);
  {Default is no file name - refers to executable file for application}
  FileName := '';
end;

destructor TVersionInfo.Destroy;
  {Class destructor}
begin
  {Ensure that info buffer is freed if allocated}
  if FPInfoBuffer <> nil then
    StrDispose(FPInfoBuffer);
  inherited Destroy;
end;

procedure TVersionInfo.ClearProperties;
  {Set that file version info not read - this effectively clears properties
  since each property read access method checks this flag before returning
  result}
begin
  FHaveInfo := False;
end;

procedure TVersionInfo.ReadVersionInfo;
  {Read version info from file}
type
  TPFFI = ^Tvs_FixedFileInfo;    {pointer to Tvs_FixedFileInfo structure}

  TLangCharSet = record          {record to hold language & char set codes}
    Lang, CharSet : Word;
  end;
  TPLangCharSet = ^TLangCharSet;  {pointer to TLangCharSet}
var
  PFileName : PChar;              {0 terminated string for file name}
  Len : UINT;                    {length of structures returned from API calls}
  Ptr : Pointer;                  {pointer to version info structures}
  PLCSet : TPLangCharSet;        {pointer to language & char set array element}
  InfoSize : DWORD;              {size of info buffer}
  Dummy : DWORD;                  {variable to hold 0 in GetFileVersionInfoSize}
begin
  {Record default value of HaveInfo property - no info read}
  FHaveInfo := False;
  {Allocate storage & copy file name to 0 terminated string}
  PFileName := StrAlloc(Length(FFileName) + 1);
  StrPCopy(PFileName, FFileName);
  {Record required size of version info buffer}
  InfoSize := GetFileVersionInfoSize(PFileName, Dummy);
  {Check that there was no error}
  if InfoSize > 0 then
  begin
    {Found info size OK}
    {Ensure we have a sufficiently large buffer allocated}
    GetInfoBuffer(InfoSize);
    {Read file version info into storage and check this has happened
    successfully}
    if GetFileVersionInfo(PFileName, Dummy, InfoSize, FPInfoBuffer) then
    begin
      {Success - we've read file version info to storage OK}
      FHaveInfo := True;
      {Get fixed file info & copy to own storage}
      VerQueryValue(FPInfoBuffer, '\', Ptr, Len);
      FFixedInfo := TPFFI(Ptr)^;
      {Get first translation table info}
      {get the info}
      VerQueryValue(FPInfoBuffer, '\VarFileInfo\Translation', Ptr, Len);
      {make our pointer point to it}
      PLCSet := TPLangCharSet(Ptr);
      {record first entry in langauge/char-set table - we ignore all (any)
      others}
      FLanguageCode := PLCSet^.Lang;
      FCharSetCode := PLCSet^.CharSet;
      {build a string holding language/char-set info}
      FTransStr := Format('%4.4x%4.4x',[FLanguageCode, FCharSetCode]);
    end;
  end;
  {dispose of storage for file name}
  StrDispose(PFileName);
end;

function TVersionInfo.GetStringFileInfo(Index : integer) : string;
  {Read access method for all string file info properties - returns appropriate
  string for the given property}
var
  CommandBuf : array[0..255] of char;  {buffer to build API call command str}
  Ptr : Pointer;                        {pointer to result of API call}
  Len : UINT;                          {length of structure returned from API}
const
  CNames : array[0..11] of string[20] = {names of all string file info strings}
    ('Comments', 'CompanyName', 'FileDescription', 'FileVersion',
    'InternalName', 'LegalCopyright', 'LegalTrademarks', 'OriginalFileName',
    'PrivateBuild', 'ProductName', 'ProductVersion', 'SpecialBuild');
begin
  {Set default failure result to empty string}
  Result := '';
  {Check if we have valid information recorded in info buffer - exit if not}
  if not FHaveInfo then Exit;
  {Build API call command string for reading string file info for required
  language and character set}
  StrPCopy(CommandBuf, '\StringFileInfo\' + FTransStr + '\' + CNames[Index]);
  {Call API to get required string and return it if successful}
  if VerQueryValue(FPInfoBuffer, CommandBuf, Ptr, Len) then
    Result := StrPas(PChar(Ptr));
end;

procedure TVersionInfo.GetInfoBuffer(Len : DWORD);
  {Allocate an info buffer of required size, ensuring that any previous buffer
  is first cleared}
begin
  if FPInfoBuffer <> nil then
    StrDispose(FPInfoBuffer);
  FPInfoBuffer := StrAlloc(Len);
end;

procedure TVersionInfo.SetFileName(AName : string);
  {Write access method for FileName property - action at design time is
  different to run time}
begin
  if csDesigning in ComponentState then
    {We are designing, simply record the required name}
    FFileName := AName
  else
  begin
    {It's run-time}
    {use Application exec file name if name is ''}
    if AName = '' then
      FFileName := Application.ExeName
    else
      FFileName := AName;
    {Clear all properties and read file version info for new file}
    ClearProperties;
    ReadVersionInfo;
  end;
end;

function TVersionInfo.GetFileVersionNumber : TVersionNumber;
  {Read access method for FileVersionNumber property}
begin
  if FHaveInfo then
  begin
    {We've got some file version info - fill structure with required info}
    Result.V1 := HiWord(FFixedInfo.dwFileVersionMS);
    Result.V2 := LoWord(FFixedInfo.dwFileVersionMS);
    Result.V3 := HiWord(FFixedInfo.dwFileVersionLS);
    Result.V4 := LoWord(FFixedInfo.dwFileVersionLS);
  end
  else
  begin
    {We've not got any file version info - set structure to zeros}
    Result.V1 := 0;
    Result.V2 := 0;
    Result.V3 := 0;
    Result.V4 := 0;
  end;
end;

function TVersionInfo.GetProductVersionNumber : TVersionNumber;
  {Read access method for ProductVersionNumber property}
begin
  if FHaveInfo then
  begin
    {We've got some file version info - fill structure with required info}
    Result.V1 := HiWord(FFixedInfo.dwProductVersionMS);
    Result.V2 := LoWord(FFixedInfo.dwProductVersionMS);
    Result.V3 := HiWord(FFixedInfo.dwProductVersionLS);
    Result.V4 := LoWord(FFixedInfo.dwProductVersionLS);
  end
  else
  begin
    {We've not got any file version info - set structure to zeros}
    Result.V1 := 0;
    Result.V2 := 0;
    Result.V3 := 0;
    Result.V4 := 0;
  end;
end;

function TVersionInfo.GetFileOS : DWORD;
  {Read access method for FileOS property - return required value if we have
  some file version info and 0 if we haven't}
begin
  if FHaveInfo then
    Result := FFixedInfo.dwFileOS
  else
    Result := 0;
end;

function TVersionInfo.GetFileType : DWORD;
  {Read access method for FileType property - return required value if we have
  some file version info and 0 if we haven't}
begin
  if FHaveInfo then
    Result := FFixedInfo.dwFileType
  else
    Result := 0;
end;

function TVersionInfo.GetFileSubType : DWORD;
  {Read access method for FileSubType property - return required value if we
  have some file version info and 0 if we haven't}
begin
  if FHaveInfo then
    Result := FFixedInfo.dwFileSubType
  else
    Result := 0;
end;

function TVersionInfo.GetFileFlagsMask : DWORD;
  {Read access method for FileFlagsMask property - return required value if we
  have some file version info and 0 if we haven't}
begin
  if FHaveInfo then
    Result := FFixedInfo.dwFileFlagsMask
  else
    Result := 0;
end;

function TVersionInfo.GetFileFlags : DWORD;
  {Read access method for FileFlags property - return required value if we have
  some file version info and 0 if we haven't}
begin
  if FHaveInfo then
    Result := FFixedInfo.dwFileFlags
  else
    Result := 0;
end;

function TVersionInfo.GetLanguage : string;
  {Read access method for Language property - return string describing language
  if we have some version info and empty string if we haven't}
var
  Buf : array[0..255] of char;  {buffer for storing langauge string from API
                                call}
begin
  if HaveInfo then
  begin
    {We've got some file version info - get language name from API}
    VerLanguageName(FLanguageCode, Buf, 255);
    Result := StrPas(Buf);
  end
  else
    {No info}
    Result := '';
end;

function TVersionInfo.GetCharSet : string;
  {Read access method for CharSet property - return string describing character
  setif we have some version info and empty string if we haven't}
const
  CCharSets : array[0..11] of record
    Code : Word;
    Str : string[40];
  end = (        {structure of code numbers and char-set names}
    (Code: 0;    Str: '7-bit ASCII'),
    (Code: 932;  Str: 'Windows, Japan (Shift - JIS X-0208)'),
    (Code: 949;  Str: 'Windows, Korea (Shift - KSC 5601)'),
    (Code: 950;    Str: 'Windows, Taiwan (GB5)'),
    (Code: 1200;    Str: 'Unicode'),
    (Code: 1250;    Str: 'Windows, Latin-2 (Eastern European)'),
    (Code: 1251;    Str: 'Windows, Cyrillic'),
    (Code: 1252;    Str: 'Windows, Multilingual'),
    (Code: 1253;    Str: 'Windows, Greek'),
    (Code: 1254;    Str: 'Windows, Turkish'),
    (Code: 1255;    Str: 'Windows, Hebrew'),
    (Code: 1256;    Str: 'Windows, Arabic')
  );
var
  I : integer;    {loop control}
begin
  if HaveInfo then
  begin
    {We've got some file version info}
    {record default result - unknown}
    Result := 'Unknown';
    {scan table of codes looking for correct entry, if any}
    for I := 0 to 11 do
      if FCharSetCode = CCharSets[I].Code then
      begin
        {found one - record its name}
        Result := CCharSets[I].Str;
        Exit;
      end;
  end
  else
    {No info}
    Result := '';
end;

{ --- Component registration routine --- }

procedure Register;
begin
  RegisterComponents('Borrisholt', [TVersionInfo]);
end;

end.
Avatar billede egeskov Nybegynder
02. oktober 2002 - 20:37 #2
Det ser da skide
Avatar billede egeskov Nybegynder
02. oktober 2002 - 20:38 #3
...godt ud - ville jeg havde skrevet. Tak skal du have !)
Avatar billede borrisholt Novice
02. oktober 2002 - 20:42 #4
Så kan du jo selv besteme hvilke oplysninger du vil have med :-)

Jens B
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester