Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Version der BPL ermitteln (https://www.delphipraxis.net/132996-version-der-bpl-ermitteln.html)

oki 23. Apr 2009 13:19


Version der BPL ermitteln
 
Hallo Leute,

ich möchte in meinem Programm eine Funktion implementieren, die mir die Versionsnummer meiner eigenen verwendeten BPL ausgiebt. Das natürlich nicht, indem ich die Versionsnummer in den Code schreibe! :lol:

Der Grund ist folgender. Ich habe eine eigene BPL geschrieben, die durch mehrere meiner Programme als Designzeit BPL genutzt wird. Da die BPL fortlaufend erweitert wird und zwischendurch immer neue Programme entsehen, die diese BPL einbinden möchte ich später das entsprechende Programm fragen können, mit welcher meiner BPL-Version es compiliert wurde. Es geht also nicht um die Versionsnummer des eigentlichen Programmes, sondern um die Version der gelinkten BPL.

Der Sinn der Sache ist, dass ich an Hand meiner Versionskontrolle prüfen kann, welcher Funktionsumfang im Programm enthalten ist, der durch die entsprechende Version der BPL zum Zeitpunkt des Compilings vorliegt.

Schön, wenn mir da einer auf die Sprünge helfen kann,

Dank im Voraus und Gruß

oki

shmia 23. Apr 2009 14:10

Re: Version der BPL ermitteln
 
Ein BPL ist ja im Grunde eine DLL.
Ein DLL kann eine VersionInfo Resource enthalten, die man auslesen kann.
Auch der Windows Explorer kann diese Informationen auslesen und anzeigen (rechtsklick->Eigenschaften).
ich schreibe das nur, damit wir alle vom Gleichen reden.
Über die Optionen des Package kann man die VersionInfo editieren und Delphi schreibt die Resource in die BPL.

Also heist die Frage: wie kann man die Versionsinfo einer beliebigen DLL, EXE oder anderen Datei im PE-Format auslesen?
Versionsinfo auslesen
In der JCL gibt es übrigens die Klasse TJclFileVersionInfo, die keine Wünsche mehr offen lässt.

DevilsCamp 23. Apr 2009 14:58

Re: Version der BPL ermitteln
 
Zitat:

Zitat von shmia
Also heist die Frage: wie kann man die Versionsinfo einer beliebigen DLL, EXE oder anderen Datei im PE-Format auslesen?
Versionsinfo auslesen
In der JCL gibt es übrigens die Klasse TJclFileVersionInfo, die keine Wünsche mehr offen lässt.

Was aber, wenn die BPL statisch verlinkt wird?
Dann bekommt man doch immer nur die aktuelle Version, oder etwa nicht?

oki 23. Apr 2009 15:21

Re: Version der BPL ermitteln
 
Hi shmia,
ja, dass kenne ich und ist auch nicht das Problem. Ich mache es aber so, wie es DevilsCamp vermutet. Ich linke die BPL statisch in die Exe. Und genau da steckt mein Problem.
Alle Einwände ich sollte die BPL dynamisch laden kann ich hier gleich abwürgen. Es sollen keine BPL mit auf den Zielrechner. Nur die Exe.

Gruß oki

shmia 23. Apr 2009 15:23

Re: Version der BPL ermitteln
 
Zitat:

Zitat von DevilsCamp
Was aber, wenn die BPL statisch verlinkt wird?
Dann bekommt man doch immer nur die aktuelle Version, oder etwa nicht?

Wenn die Units statisch in die Applikation gelinkt wurden, dann werden ja keine BPL benützt oder gebraucht.
Damit entfällt auch die Notwendigkeit die Version abzufragen.

Falls du mit statisch verlinkt meinst, dass die BPLs gleich beim Programmstart geladen werden, dann könnte man auch so vorgehen.
Mit GetModuleHandle('name_der_Bibliothek.bpl') das Handle holen, dann LoadResource() und FindResource() und LockResource() die VersionInfo Daten auslesen.
Irgendwo verwaltet die VCL (oder Windows ?) auch alle Handles der geladenen BPLs; so könnte man die VersionInfos auslesen ohne die Namen der beteiligten BPLs kennen zu müssen.

oki 23. Apr 2009 15:46

Re: Version der BPL ermitteln
 
Hallo shmia,
sorry für die ungenaue Beschreibung. Die Exe lädt die BPL nicht, sondern ist als DesigntimePackage im Projekt der Exe enthalten. Die Exe ist ohne die Benutzung von RuntimePackages compiliert.
Richtig, :gruebel: , für diesen Fall wird die BPL ja gar nicht in die Exe mit aufgenommen, sondern die Units mit gelinkt. Blöd, wie bekomme ich da eine automatische Versionskontrolle hin außer das in einer eigenen Funktion immer händisch nachpflegen zu müssen.

Ich hatte schon überlegt das im Pre- oder AfterBuild unterzubringen. Aber da bekomme ich es ja auch nicht in die Exe sondern nur in eine externe Datei. Oder kennt jemand eine Möglichkeit wie ich das im PreBuild in die Ressource gepackt bekomme? Das ist doch eine Idee :?:

Gruß oki

DevilsCamp 23. Apr 2009 15:58

Re: Version der BPL ermitteln
 
Zitat:

Zitat von shmia
Zitat:

Zitat von DevilsCamp
Was aber, wenn die BPL statisch verlinkt wird?
Dann bekommt man doch immer nur die aktuelle Version, oder etwa nicht?

Wenn die Units statisch in die Applikation gelinkt wurden, dann werden ja keine BPL benützt oder gebraucht.
Damit entfällt auch die Notwendigkeit die Version abzufragen.

Finde ich nicht. Genau DANN ist es doch sinnvoll herauszufinden, auf welchen Stand die Komponenten, Klassen, usw. sind.

Ideal wäre aber, wenn es eine Mischung aus Version der DLL und Konstante gäbe. Also ein Macro, das bei jedem Build die aktuelle Version als Variable/Konstante zur Verfügung stellt, deren Wert man im Programm abfragen kann.

shmia 23. Apr 2009 16:31

Re: Version der BPL ermitteln
 
Die JCL unterstützt auch das sogenannte Unit-Versioning.
Dazu kann man in jede Unit, die man überwachen will einen const Record einfügen:
Delphi-Quellcode:
{$IFDEF UNITVERSIONING}
const
  UnitVersioning: TUnitVersionInfo = (
    RCSfile: '$URL: [url]https://jcl.svn.sourceforge.net:443/svnroot/jcl/tags/JCL-1.101-Build2725/jcl/source/common/JclFileUtils.pas[/url] $';
    Revision: '$Revision: 2101 $';
    Date: '$Date: 2007-08-04 22:00:43 +0200 (sam., 04 août 2007) $';
    LogPath: 'JCL\source\common'
    );
{$ENDIF UNITVERSIONING}
....
{$IFDEF UNITVERSIONING}
initialization
  RegisterUnitVersion(HInstance, UnitVersioning);

finalization
  UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}

end.
Es gibt dann Funktionen (Unit JclUnitVersioning), um diese Informationen auszulesen.
Dieses System funktioniert auch dann, wenn BPLs benützt werden.

oki 23. Apr 2009 16:33

Re: Version der BPL ermitteln
 
Zitat:

Finde ich nicht. Genau DANN ist es doch sinnvoll herauszufinden, auf welchen Stand die Komponenten, Klassen, usw. sind.
Genau so steht es im Moment mit meinem Bedarf. Ich muss wissen, welchen Stand die BPL zum Zeitpunkt der Erstellung der jeweiligen Exe hatte.
Die Frage ist aber weiterhin, wie ich die Version der BPL in die Exe bekommen.

Gruß oki

oki 23. Apr 2009 16:37

Re: Version der BPL ermitteln
 
Zitat:

Zitat von shmia
Die JCL unterstützt auch das sogenannte Unit-Versioning.
Dazu kann man in jede Unit, die man überwachen will einen const Record einfügen:
Delphi-Quellcode:
{$IFDEF UNITVERSIONING}
const
  UnitVersioning: TUnitVersionInfo = (
    RCSfile: '$URL: [url]https://jcl.svn.sourceforge.net:443/svnroot/jcl/tags/JCL-1.101-Build2725/jcl/source/common/JclFileUtils.pas[/url] $';
    Revision: '$Revision: 2101 $';
    Date: '$Date: 2007-08-04 22:00:43 +0200 (sam., 04 août 2007) $';
    LogPath: 'JCL\source\common'
    );
{$ENDIF UNITVERSIONING}
....
{$IFDEF UNITVERSIONING}
initialization
  RegisterUnitVersion(HInstance, UnitVersioning);

finalization
  UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}

end.
Es gibt dann Funktionen (Unit JclUnitVersioning), um diese Informationen auszulesen.
Dieses System funktioniert auch dann, wenn BPLs benützt werden.

Jo, sieht erst mal sehr gut aus. Ich geb aber ehrlich zu, dass ich noch keinen blassen Schimmer habe, wie ich über die Exe mittels Funktion an die Version komme.
Die nächste Frage ist, wie gleiche ich die Version in UnitVersioning auf die Version der BPL ab.

Fragen über Fragen, auf deutsch ich seh nicht durch. :mrgreen:

Gruß oki

oki 24. Apr 2009 09:21

Re: Version der BPL ermitteln
 
Push :oops:

Satty67 24. Apr 2009 09:29

Re: Version der BPL ermitteln
 
Etwas Handarbeit... beim erweitern der BPL eine kleines Programm starten, das die Version der BPL's in eine INC-Datei schreibt, die dann ins Programm eingebunden wird.

Wobei es dafür ja eine Lösung per IDE-Experte geben müsste, der das direkt vorm compilieren erledigt?

oki 24. Apr 2009 10:07

Re: Version der BPL ermitteln
 
Zitat:

Zitat von Satty67
Etwas Handarbeit... beim erweitern der BPL eine kleines Programm starten, das die Version der BPL's in eine INC-Datei schreibt, die dann ins Programm eingebunden wird.

Wobei es dafür ja eine Lösung per IDE-Experte geben müsste, der das direkt vorm compilieren erledigt?

Joop, so hatte ich mir das gedacht.
Jetzt stellt sich für mich nur noch die Frage, wie ich die Inc-Datei automatisch schreiben kann. Ich geb ehrlich zu, dass ich mit Inc-Dateien bis Dato noch nichts am Hut hatte :oops: . Kleiner Tipp wie ich die verwende (Wert auslese)?

Gruß oki

Satty67 24. Apr 2009 10:50

Re: Version der BPL ermitteln
 
Ich schreib mal über alles was....

Also Includes sind auch nur normale PAS oder Text-Dateien. Die Zeilen darin werden an der entsprechenden Stelle wie Copy&Paste eingefügt. Also ist der Inhalt beliebig, solange er Pascal-Quellcode entspricht (Dateiname ist auch egal, auch wenn *.pas default ist). ...einbinden per {$I XYZ_BBL.VER} and der gewünschen "Paste"-Stelle

Erzeugen sollte ja klar sein... eine Exe, die DLL-Version abfragt und z.B. den Wert als const-Deklaration in die Include-Datei schreibt. z.B.
Code:
const
  XYZ_BPL_Version : Double = 2.9;
Richtig spannend ist, wie diese Exe von der IDE vorm compilieren ausgeführt wird (also ohne manuellem Start). Das müsste gehen und das weis hier auch sicher jemand... nur ich nicht ;)

Noch genialer wäre ein IDE-Experte, der vorm compilieren einen Resource-String in die Resource des zu compilierenden Projekts reinschreibt.

himitsu 24. Apr 2009 11:21

Re: Version der BPL ermitteln
 
also ohne Experte wohl einfach so
Delphi-Quellcode:
// Projektoptionen > Pre-Build:
CreateBPLVersionInfo.exe


// einbinden / prüfen:
{$INCLUDE "BPLVersion.inc"}

...
Caption := MyBPLVersion;


// die BPLVersion.inc
const MyBPLVersion = '1.2.3.4';
aber besser wohl so ... da hat man auch gleich eine bessere Möglichkeit zu prügen ob die Pre/Post-Build-Ereignisse in den Optionen eingetragen sind
und somit Version möglichst aktuell wäre.
Delphi-Quellcode:
// Projektoptionen > Pre-Build:
CreateBPLVersionInfo.exe "BPL-Name" "MyBPLVersion" "BPLVersion.inc"


// Projektoptionen > Post-Build:
DEL "BPLVersion.inc"


// einbinden / prüfen:
{$INCLUDE "BPLVersion.inc"}
{$IF not Declared(MyBPLVersion))
  {$MESSAGE Error 'MyBPLVersion ist nicht definiert (eventuell Pre/Post-Build-Ereignisse prüffen)'}
{$IFEND}

...
Caption := MyBPLVersion;


// die .INC (z.B. "BPLVersion.inc")
const MyBPLVersion = '1.2.3.4';
CreateBPLVersionInfo.exe bracht ja nur 'ne kleine Consolenanwendung sein, welche die Version ausließt und die .INC erstellt (über die Parameter könnte man dieses dann so gestalten, daß man dieses eine Programm für mehrere BPLs verwenden kann)

oki 28. Apr 2009 09:34

Re: Version der BPL ermitteln
 
Hi Leute,

erstmal wieder Dank für die Antworten. Sorry, dass ich mich erst so spät melde, aber aus irgend welchen Gründen hatte ich keine Mails über neue Beiträge in dem Thread bekommen. Deshalb hatte ich mich ran gemacht und die Erstellung der inc über ein kleines eigenes Tool getestet. Das habe ich in mein PostBuild aufgenommen. Eigentlich habe ich es genau so bemacht, wie es himitsu beschrieben hat.

Damit klappt das jetzt alles super!

Hier mal der Code meines kleinen Tools:
Delphi-Quellcode:
 (*
   Die Konsolenanwendung generiert eine IncludeDatei, die die Versionsnummer der angegebenen
   BPL ermittelt.
   Zum Aufruf der Anwendung müssen folgende Parameter übergeben werden:
   BPLVersion_inc.exe [BPLName] [DestDir]
   - BPLName
       ist der Name der zu verarbeitenden Datei incl. Pfadangabe
   - DestDir
       ist das Verzeichnis, in dem die Datei angelegt wird. Ist das Verzeichnis nicht
       vorhanden, so wird dieses durch BPLVersion_inc angelegt.
   Der Name der Datei ist BPLVersion_[BPLName].inc

   Die aufzurufende Funktion lautet:
   function GetBPLVersion_[BPLName] : String;

   BPLName ist der Name der BPL ohne Pfad.
 *)
program BPLVersion_inc;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Classes,
  FileVers; // eigene Unit zur Ermittlung der Versionsnummer

var AList : TStringList;
     BPlName, BPlVersion, DestPath, s : String;
    Counter : Integer;
begin
  try
    try
      AList := TStringList.Create;
      BPlName := ParamStr(1);
      DestPath := ParamStr(2);
      ForceDirectories(DestPath);
      if (BPLName = '') or (not FileExists(BPLName)) then begin
        raise Exception.Create('BPL "' + BPLName + '" nicht gefunden!');
      end;
      BPLVersion := GetFileVersionsString(BPLName);
      BPLName :=ExtractFileName(BPLName);
      Counter := 1;
      s := '';
      while (not (BPLName[Counter] = '.')) or (Counter = Length(BPLName)) do begin
        s := s + BPLName[Counter];
        inc(Counter);
      end;
      AList.Add('function GetBPLVersion_' + s + ' : String;');
      AList.Add('begin');
      AList.Add(' Result := ''' + BPLVersion + '''');
      AList.Add('end;');

      AList.SaveToFile(IncludeTrailingPathDelimiter(DestPath) +
        'BPLVersion_' + s + '.inc');
    finally
      AList.Free;
    end;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.
Ich hab mir dabei nicht unbedingt die größten Kopfschmerzen zur Eleganz gemacht. Es funzt und das reicht mir. In meinem Projektquellcode implementiere ich an der entsprechenden Stelle die Compilerdirektive:
Delphi-Quellcode:
{$I BPLVersion_MyBPL.inc}
und kann dann auf die Funktion zugreifen. Ich habe das gleich mit den entsprechenden Übergabepareametern versehen, so kann ich für jede BPL eine eigene Inc-Datei mit eigenem Funktionsaufruf generieren. Weitere Tools für andere BPL's sind somit nicht nötig. Das sollte auch mit DLL's gehen, brauch ich aber nicht. Sinnvollerweise sollte der Code des Tools dann dahingehend erweitert werden.

Wie gesagt, in den Projektoptionen das ganze ins PostBuild (BPLVersion_inc.exe "MyBPL" "C:\Programmierung\MyBPLProject").

Dank euch allen noch mals und Gruß

oki

schöni 28. Apr 2009 12:25

Re: Version der BPL ermitteln
 
Zitat:

Zitat von Satty67
Ich schreib mal über alles was....

Also Includes sind auch nur normale PAS oder Text-Dateien. Die Zeilen darin werden an der entsprechenden Stelle wie Copy&Paste eingefügt. Also ist der Inhalt beliebig, solange er Pascal-Quellcode entspricht (Dateiname ist auch egal, auch wenn *.pas default ist). ...einbinden per {$I XYZ_BBL.VER} and der gewünschen "Paste"-Stelle

Erzeugen sollte ja klar sein... eine Exe, die DLL-Version abfragt und z.B. den Wert als const-Deklaration in die Include-Datei schreibt. z.B.
Code:
const
  XYZ_BPL_Version : Double = 2.9;
Richtig spannend ist, wie diese Exe von der IDE vorm compilieren ausgeführt wird (also ohne manuellem Start). Das müsste gehen und das weis hier auch sicher jemand... nur ich nicht ;)

Da gab es mal Innerfuse Pascal Script und auch RemObjects Pascal Script. Ließe sich damit nicht ein Pascal Interpreter bauen? Der müsste natürlich dann als IDE Experte verfügbar gemacht werden.

oki 28. Apr 2009 13:23

Re: Version der BPL ermitteln
 
Zitat:

Zitat von schöni
Zitat:

Zitat von Satty67
Ich schreib mal über alles was....

Also Includes sind auch nur normale PAS oder Text-Dateien. Die Zeilen darin werden an der entsprechenden Stelle wie Copy&Paste eingefügt. Also ist der Inhalt beliebig, solange er Pascal-Quellcode entspricht (Dateiname ist auch egal, auch wenn *.pas default ist). ...einbinden per {$I XYZ_BBL.VER} and der gewünschen "Paste"-Stelle

Erzeugen sollte ja klar sein... eine Exe, die DLL-Version abfragt und z.B. den Wert als const-Deklaration in die Include-Datei schreibt. z.B.
Code:
const
  XYZ_BPL_Version : Double = 2.9;
Richtig spannend ist, wie diese Exe von der IDE vorm compilieren ausgeführt wird (also ohne manuellem Start). Das müsste gehen und das weis hier auch sicher jemand... nur ich nicht ;)

Da gab es mal Innerfuse Pascal Script und auch RemObjects Pascal Script. Ließe sich damit nicht ein Pascal Interpreter bauen? Der müsste natürlich dann als IDE Experte verfügbar gemacht werden.

Unter D2007 wie gesagt einfach in das PostBuild in den Projektoptionen. Mein altes Delphi 5 kannte das natürlich noch nicht. Wie es bei D7 mit PostBuild steht ... Dann ist das mit dem Automatismus natürlich nicht mehr so automatisch (zumindest einfach).

Für meine Belange und IDE ist es in der beschriebenen Variante aber ideal.

Gruß oki


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:59 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz