Difference between revisions of "Show Application Title, Version, and Company"

From Free Pascal wiki
Jump to navigationJump to search
(→‎FPC 2.7.1/trunk: Works on Linux, too. probably osx as well...)
Line 58: Line 58:
 
Implementation in FPC 2.7.1 using [[fcl-res]]: [http://wiki.lazarus.freepascal.org/User_Changes_Trunk#TVersionInfo_.28fileinfo_unit.29_re-implemented_in_a_platform_independent_way]
 
Implementation in FPC 2.7.1 using [[fcl-res]]: [http://wiki.lazarus.freepascal.org/User_Changes_Trunk#TVersionInfo_.28fileinfo_unit.29_re-implemented_in_a_platform_independent_way]
  
The code belows shows how to get stanard executable info out of .exe/.dll files (Windows format) regardless of the platform the code is running on.
+
The code belows shows how to get executable info out of  
Depending on the format Lazarus uses to encode version info on other platforms, it could be extended for those platforms (e.g. ELF for Linux, MACHO for OSX):
+
* .exe/.dll files (Windows format)  
 +
* Lazarus-compiled ELF executables (Linux)
 +
* Lazarus-compiled MACH-O executables (OSX) (untested, please update this once tested)
 +
regardless of the platform the code is running on.
 +
 
 
<syntaxhighlight>
 
<syntaxhighlight>
 
program printfileinfo;
 
program printfileinfo;
{ Displays file version info for Windows PE executables (runs on Windows, Linux, OSX...)}
+
{ Displays file version info for  
 +
- Windows PE executables
 +
- Linux ELF executables (compiled by Lazarus)
 +
- probably OSX MACH-O executables (compiled by Lazarus)
 +
Runs on Windows, Linux, OSX...)
 +
}
  
 
{$mode objfpc}{$H+}
 
{$mode objfpc}{$H+}
Line 74: Line 83:
 
   , fileinfo
 
   , fileinfo
 
   , winpeimagereader {need this for reading exe info}
 
   , winpeimagereader {need this for reading exe info}
   {todo: add required image formats, e.g.
+
   , elfreader {needed for reading ELF executables}
  machoreader for osx
+
   , machoreader {needed for reading MACH-O executables}
  elfreader for linux
 
   and verify if this works for those file formats}
 
 
   ;
 
   ;
  
 
var
 
var
   WindowsInfo: TFileVersionInfo;
+
   FileVerInfo: TFileVersionInfo;
 
begin
 
begin
 
   if Paramcount=0 then
 
   if Paramcount=0 then
Line 88: Line 95:
 
     halt(1);
 
     halt(1);
 
   end;
 
   end;
   WindowsInfo:=TFileVersionInfo.Create(nil);
+
   FileVerInfo:=TFileVersionInfo.Create(nil);
 
   try
 
   try
     WindowsInfo.FileName:=paramstr(1);
+
     FileVerInfo.FileName:=paramstr(1);
     WindowsInfo.ReadFileInfo;
+
     FileVerInfo.ReadFileInfo;
     writeln('Company: ',WindowsInfo.VersionStrings.Values['CompanyName']);
+
     writeln('Company: ',FileVerInfo.VersionStrings.Values['CompanyName']);
     writeln('File description: ',WindowsInfo.VersionStrings.Values['FileDescription']);
+
     writeln('File description: ',FileVerInfo.VersionStrings.Values['FileDescription']);
     writeln('File version: ',WindowsInfo.VersionStrings.Values['FileVersion']);
+
     writeln('File version: ',FileVerInfo.VersionStrings.Values['FileVersion']);
     writeln('Internal name: ',WindowsInfo.VersionStrings.Values['InternalName']);
+
     writeln('Internal name: ',FileVerInfo.VersionStrings.Values['InternalName']);
     writeln('Legal copyright: ',WindowsInfo.VersionStrings.Values['LegalCopyright']);
+
     writeln('Legal copyright: ',FileVerInfo.VersionStrings.Values['LegalCopyright']);
     writeln('Original filename: ',WindowsInfo.VersionStrings.Values['OriginalFilename']);
+
     writeln('Original filename: ',FileVerInfo.VersionStrings.Values['OriginalFilename']);
     writeln('Product name: ',WindowsInfo.VersionStrings.Values['ProductName']);
+
     writeln('Product name: ',FileVerInfo.VersionStrings.Values['ProductName']);
     writeln('Product version: ',WindowsInfo.VersionStrings.Values['ProductVersion']);
+
     writeln('Product version: ',FileVerInfo.VersionStrings.Values['ProductVersion']);
 
   finally
 
   finally
     WindowsInfo.Free;
+
     FileVerInfo.Free;
 
   end;
 
   end;
 
end.
 
end.

Revision as of 15:25, 26 December 2013

This article is a placeholder containing links to code, some of which might be obsolete as of late 2013 (Lazarus 1.0, FPC 2.6.2).

Overview

From its earliest versions, Microsoft Windows had the capability of storing version information etc. in an executable file. Support for that was added to Delphi around v3, and was part-functional in Lazarus 0.9.24.

Linux

There is no implicit provision in the ELF file format for version numbers, copyright and so on, but Lazarus stores this in resource sections. Reading the information back at runtime relies on FPC units, below are some pointers that might be useful.

Implementations using FPC 2.6.x

Contribution via the mailing list: [1]

Use this like

 FUNCTION resourceVersionInfo: STRING;
 
 (* Unlike most of AboutText (below), this takes significant activity at run-    *)
 (* time to extract version/release/build numbers from resource information      *)
 (* appended to the binary.                                                      *)
 
 VAR     Stream: TResourceStream;
         vr: TVersionResource;
         fi: TVersionFixedInfo;
 
 BEGIN
   RESULT:= '';
   TRY
 
 (* This raises an exception if version info has not been incorporated into the  *)
 (* binary (Lazarus Project -> Project Options -> Version Info -> Version        *)
 (* numbering).                                                                  *)
 
     Stream:= TResourceStream.CreateFromID(HINSTANCE, 1, PChar(RT_VERSION));
     TRY
       vr:= TVersionResource.Create;
       TRY
         vr.SetCustomRawDataStream(Stream);
         fi:= vr.FixedInfo;
         RESULT := 'Version ' + IntToStr(fi.FileVersion[0]) + '.' + IntToStr(fi.FileVersion[1]) +
                ' release ' + IntToStr(fi.FileVersion[2]) + ' build ' + IntToStr(fi.FileVersion[3]) + eol;
         vr.SetCustomRawDataStream(nil)
       FINALLY
         vr.Free
       END
     FINALLY
       Stream.Free
     END
   EXCEPT
   END
 END { resourceVersionInfo } ;


Using vinfo: [2] and [3]

On an Apple OSX machine: Mac Show Application Title, Version, and Company

FPC 2.7.1/trunk

Implementation in FPC 2.7.1 using fcl-res: [4]

The code belows shows how to get executable info out of

  • .exe/.dll files (Windows format)
  • Lazarus-compiled ELF executables (Linux)
  • Lazarus-compiled MACH-O executables (OSX) (untested, please update this once tested)

regardless of the platform the code is running on.

program printfileinfo;
{ Displays file version info for 
- Windows PE executables 
- Linux ELF executables (compiled by Lazarus)
- probably OSX MACH-O executables (compiled by Lazarus)
Runs on Windows, Linux, OSX...)
}

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes,sysutils
  // FPC trunk fileinfo reads exe resources as long as you register the appropriate units
  , fileinfo
  , winpeimagereader {need this for reading exe info}
  , elfreader {needed for reading ELF executables}
  , machoreader {needed for reading MACH-O executables}
  ;

var
  FileVerInfo: TFileVersionInfo;
begin
  if Paramcount=0 then
  begin
    writeln('Missing executable filename parameters. Aborting.');
    halt(1);
  end;
  FileVerInfo:=TFileVersionInfo.Create(nil);
  try
    FileVerInfo.FileName:=paramstr(1);
    FileVerInfo.ReadFileInfo;
    writeln('Company: ',FileVerInfo.VersionStrings.Values['CompanyName']);
    writeln('File description: ',FileVerInfo.VersionStrings.Values['FileDescription']);
    writeln('File version: ',FileVerInfo.VersionStrings.Values['FileVersion']);
    writeln('Internal name: ',FileVerInfo.VersionStrings.Values['InternalName']);
    writeln('Legal copyright: ',FileVerInfo.VersionStrings.Values['LegalCopyright']);
    writeln('Original filename: ',FileVerInfo.VersionStrings.Values['OriginalFilename']);
    writeln('Product name: ',FileVerInfo.VersionStrings.Values['ProductName']);
    writeln('Product version: ',FileVerInfo.VersionStrings.Values['ProductVersion']);
  finally
    FileVerInfo.Free;
  end;
end.

Unix-only hacks

These work with Linux on various platforms, and probably with Solaris provided that the GNU-derived utilities are installed.

Getting Subversion revision information as a program-accessible string

Put this into Project options -> Compilation -> Execute before -> Command:

/bin/sh -c "echo -n C`svnversion -n`C |tr A-G %-+ >project_svnrevision.inc"

Note quote and backtick positions. The tr is converting C into another layer of quotes which is necessary for things to work as required.

Put this into the program:

   (*$IFDEF UNIX   *)
           rev= (*$I project_svnrevision.inc *) ;
   (*$ELSE         *)
           rev= 'unimplemented';
   (*$ENDIF        *)

Note that that has to be a string, since the revision number will have a non-numeric suffix if the project has been updated since it was last committed.

Renaming the final executable to include platform and timestamp

Put this into Project options -> Paths -> Unit output directory:

lib/$(TargetCPU)-$(TargetOS)

Put this into Project options -> Paths -> Target file name:

UnyokedBackend-$(TargetCPU)-$(TargetOS)-$(LCLWidgetType)

Make sure that "Apply conventions" is ticked (checked). This might vary slightly according to IDE and compiler/linker versions.

Put this into Project options -> Compilation -> Execute after -> Command:

 /bin/sh -c "mv libunyokedbackend-$(TargetCPU)-$(TargetOS)-$(LCLWidgetType).so UnyokedBackend-$(TargetCPU)-$(TargetOS)-$(LCLWidgetType).`date +%F.%R`.so"

That should be a single line. Note quote and backtick positions.