AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

RuntimePackage laden/verwenden

Ein Thema von oki · begonnen am 12. Mär 2009 · letzter Beitrag vom 19. Mär 2009
Antwort Antwort
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#1

RuntimePackage laden/verwenden

  Alt 12. Mär 2009, 12:51
Hallo Leute,

ich möchte hier für mein Problem ein neues Thema aufmachen. Begonnen hatte ich mit einer Antwort (eher weiteren Frage) in BaBuSE's Thread Probleme mit GetClass ....
Für den benannten Thread und deren Titel ist die Frage beantwortet. Mein Problem aber leider nicht. Somit möchte ich hier einen neuen Thread als offene Frage aufmachen.

Hier noch mal das, was ich machen will:
Ich habe folgende Module:
- BasePackage (enthält die Basisformulare und Komponenten; erstellt für Runtime und Designtime)
- SpezialPackage (enthält spezielle Formulare als Nachfahren der Basisformulare aus BasePackage; erstellt für Runtime)
- MyApp (enthält Nachfahren aus BasePackage und soll spezielle Formulare mittels LoadPackage aus SpezialPackage verwenden)

Dabei muß ich in MyApp mittels GetClass sowohl für die Formulare und Komponenten in BasePackage und in SpecialPackage arbeiten.
Alle benötigten Klassen sind mittels RegisterClass im initialization-Teil der Units registriert.


Mein aktuelles Problem stellt sich wie folgt das (letzer Beitrag von mir in MaBuSE's Thread):
Zitat:
Ich habe mir im Debugger die Aufrufe meiner vererbten Klasse angesehen und festgestellt, dass da ein Versatz drin ist. Das passt schon mal zu dieser Aussage:
Zitat:
Das liegt unter anderem daran, das die Adresstabellen anders aufgebaut sind, je nachdem ob die Anwendung mit oder ohne Runtime Packages arbeitet. Es werden beim Compilieren durch den Schalter RuntimePackages viele grundlegende interne Dinge komplett anders gemacht. Es ist also nicht "nur" die verwendeten Package in die Exe gelinkt, sondern wie schon Geschieben, es wird viel mehr gemacht.
So wie es aussieht trifft das jetzt genau bei mir zu. Leider drehe ich mich da im Kreis.

Meine Anwendung die das Package laden soll besitzt Formuare aus BasePackage. Konkret auch das MainForm. Somit habe ich mein BasePackage als Design- und RuntimePackage kompiliert. Ich brauch ja die Formulare und Komponenten zum Designen meiner Anwendung. Das SpezialPackage ist als Runtimepackage kompiliert und enthält ein speziellen Formular als Nachfahre eines Forms aus BasePackage. Diese SpezialPackage soll dann von meiner Anwendung zur Laufzeit nachgeladen werden.
Jetzt habe ich den Verdacht, dass meine Anwendung ja das BasePackage als Designtime-Package verwendet, obwohl ich Laufzeitpackages verwenden ausgewählt und mein BasePackage mit eingetragen habe. Wird mein SpezialPackage als Laufzeitpackage geladen, welches natürlich auch BasePackage beinhaltet, so habe ich wieder den Mischbetrieb.
Dahinter kann ich aktuell keine rechte Logik erkennen, aber die Erscheinungen lassen sich für mich mit dem gesagten erst mal nur so erklären.

Meine erste Frage
Liege ich damit richtig?

Meine zweite Frage
Welche Alternative habe ich?

Meine dritte Frage
Mache ich in meiner Exe etwas falsch mit der Einbindung der Packages und wie sorge ich konkret dafür, dass nur RuntimePackages verwendet werden?
Ja, was nun sprach Zeus, die Götter sind besoffen.

Wenn jemand helfen oder einfach Licht ins Dunkel bringen kann ... Jedwede Hilfe wird dankbar angenommen.

Gruß oki
42
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#2

Re: RuntimePackage laden/verwenden

  Alt 12. Mär 2009, 17:03
Zwischenzeitlich hat sich herausgestellt, dass mit der Anwahl "Laufzeit-Packages verwenden" eindeutig nur Laufzeitpackages von der Exe verwendet werden. Damit ist mein Verdacht hier im "Mischbetrieb" zu fahren widerlegt.

Gut so!

Mein Problem ist damit aber noch nicht behoben,

Schlecht so!

Beim Debuggen habe ich festgestellt, dass in der IDE die "blauen Punkte" an der linken Seite (also die compilierten Codezeilen) einen Zeilenversatz haben. Das passiert an der Stelle, wenn ich das Package geladen habe und bei zeilenweiser Abarbeitung mit dem Debugger dieser in eine Unit des Packages springt. Das heisst, der Debugger markiert in den Units beim debuggen die falschen Zeile. Breakpoints sind somit für die Katz! Im Ablauf ist das so, ich setze in meiner Exe einen Breakpoint vor dem Code zum Laden des Modules (LoadPackage). Steppe dann per Einzelschritt weiter bis ein Aufruf im Code einer Unit meines Packages aufgerufen wird. Der Debugger springt in das richtige Fenster, aber dort ist alles versetzt. Der code wird auch nicht richtig ausgeführt. Ich hab es getestet, indem ich die Unit in die Anwendung eingebunden habe und das ganze ohne Package laden ausprobierte. Da war alles korrekt. Nur wenn ich das Package zur Laufzeit nachlade entsteht der Käse.

Kennt jemand diese Erscheinung?

Gruß oki
42
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#3

Re: RuntimePackage laden/verwenden

  Alt 12. Mär 2009, 18:26
Musst du unbedingt Formulare vererben oder könntest du dir vorstellen auch andere objektorientierte Techniken zu verwenden?
Mein Erfahrung mit abgeleiteten Formularen ist, dass man dies besser vermeiden sollte.
Gründe:
* Änderungen im Basisformular können den Code in den abgeleiteten Formularen brechen
* unbeabsichtigte Änderungen (z.B. Verschieben eines Controls um wenige Pixel) auf dem abgel. Formular machen Probleme
* Zur Entwicklungszeit blockieren sich die versch. Instanzen der Formulare gegenseitig. Projekt schliesen und neu öffnen muss immer wieder durchexerziert werden
Andreas
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#4

Re: RuntimePackage laden/verwenden

  Alt 12. Mär 2009, 20:31
Hi schmia,

der Weg der Vererbung der Formulare ist erst mal der, den ich eingeschlagen habe. In der Regel liegen kaum weitere Komponenten auf den Basisformularen. Sie dienen eigentlich als spezialisierte Vorlagen, um das Erstellen von Anwendungen einfacher zu gestalten und ein durchgängiges Grunddesign sicher zu stellen. Natürlich neben weiteren Grundfunktionalitäten.

Für andere Techniken bin ich immer offen. Ich fand halt keine passenden für die gewünschten Anforderungen. Für den Bereich der Vererbung von Formularen gebe ich dir vollkommen recht. Damit muss ich leben.

Das aktuelle Problem kommt eigentlich aus einer anderen Ecke. Ich will für den internen Gebrauch ein Tool erstellen, in das man die spezialisierten Packages laden kann. Das Basispackage soll eigentlich nicht mehr verändert werden. Damit ich das Tool nicht jedesmal neu kompilieren muss wenn ein neues Package vorliegt will ich diese nachladen können. Dabei muss ich aber über die Klasseninformationen gehen.

Beispiel. Ein neues Formular liegt im neuen Spezialpackage vor, das ein Nachfahre vom BaseForm in Basepackage ist. Wenn ich dieses in meinem Tool creieren und anzeigen will mache ich folgendes:

Delphi-Quellcode:
procedure TSettingsMainForm.TATBPLFormsLoad;
var
  AFormClass: TPersistentClass; // hier könnte man auch TFormClass nehmen, spaart man weiter unten das Casten
  AForm : TForm;
  FormList: TStringList;
  Counter: Integer;
begin
  if FBPLModule <> 0 then
    TATBPLFormsUnload;
  if not FileExists(FSettingsProject.TATBPLName) then
    Exit;
  FBPLModule := LoadPackage(FSettingsProject.TATBPLName);
  if FBPLModule <> 0 then begin
    @GetBPLFormClasses := GetProcAddress(FBPLModule, 'GetBPLFormClasses');
    if @GetBPLFormClasses = nil then
      Exit;
    try
      FormList := TStringList.Create;
      GetBPLFormClasses(FormList); // Liste aller Formularklassen aus dem Package holen
      for Counter := 0 to FormList.Count - 1 do begin
        AFormClass := GetClass(FormList.Strings[Counter]);
        if Assigned(AFormClass) then begin
          Application.CreateForm(TComponentClass(AFormClass), AForm);
          AForm.Show;
        end;
      end;
    finally
      FreeAndNil(FormList);
    end;
  end;
end;
Entladen wird das Package an anderer Stelle.

Also, wenn du andere Ideen hast, gerne her damit. Sollte mein Anwendungsfall nicht verständlich genug sein, liefer ich mehr.

Da das mit dem den Laufzeitpackages jetzt aber wohl klar ist und die Sache prinzipiell klappen müßte, würde ich das auf diesem Weg schon gerne hin bekommen.

Gruß oki
42
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#5

Re: RuntimePackage laden/verwenden

  Alt 13. Mär 2009, 15:49
Zitat von oki:
Für andere Techniken bin ich immer offen. Ich fand halt keine passenden für die gewünschten Anforderungen. Für den Bereich der Vererbung von Formularen gebe ich dir vollkommen recht. Damit muss ich leben.
Du versuchst wohl allen deinen Formularen das gleiche Look & Feel zu geben.
Eine Möglichkeit wäre Frames zu verwenden.
Ich habe z.B. einen "NavigatorFrame" auf vielen meinen Formularen.
Es ist eine Zusammenfassung von DBNavigator und einem Suchen- ,OK- und Abbrechen-Button.
Dann gibt es bei mir z.B. einen LoggingFrame:
Eine Memo für Textmeldungen + Combobox für das Datumsuhrzeitformat + Combobox für einen Filter Info, Warnungen oder Fehler.

Man sollte die Frames aber nicht überfrachten.
Auch das Ableiten von Frames kann ich nicht empfehlen; das macht nur Probleme.

Eine andere Möglichkeit wäre eine Form-Factory.
Anstatt überall folgenden Code zu verwenden:
Form42 := TForm42.Create(nil); lässt man die Formulare indirekt erzeugen:
Form42 := TFormFactory.CreateForm(TForm42, nil) as TForm42; Die Methode CreateForm() kann z.B. so aussehen:
Delphi-Quellcode:
class function TFormFactory.CreateForm(AClass: TComponentClass;Owner: TComponent): TComponent;
begin
   Result := AClass.Create(Owner);
   With(TForm(Result) do
   begin
     // Formulare sollen nicht an festen Positionen erscheinen; das soll Windows machen
     if Position = poDesigned then
        Position := poDefaultPosOnly;

     // jedes Formulare wird um ein SystemMenu erweitert,
     // damit alle Formulare zusätzlich den Eintrag "Screenshot" und "Drucken" bekommen
     AddSpecialSystemMenue(Handle);
   end;
end;
Man kann mehrere Factory-Methoden verwenden.
Delphi-Quellcode:
class function TFormFactory.CreateModalDialogForm(AClass: TComponentClass;Owner: TComponent): TComponent;
begin
   Result := CreateForm(AClass, Owner);
   With(TForm(Result) do
   begin
      // alle Formulare, die für einen modalen Dialog gedacht sind
      // sollen ROT sein
      Color := clRed;

      // ausserdem sollen diese Dialoge ein besonderes Icon bekommen
      Icon := MyWarningIcon;
   end;
end;
Die Möglichkeiten sind vielfältig.
Man kann z.B. mit einer Funktion über alle TLabels des gerade erzeugten Formulars gehen
und Font.Name auf einen bestimmten Wert setzen.
Und schon haben alle Labels einen bestimmten Font auch wenn sie zur Entwicklungszeit auf "MS Sans Serif" waren.
Miniaturansicht angehängter Grafiken
loggingframe_931.gif  
Andreas
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#6

Re: RuntimePackage laden/verwenden

  Alt 15. Mär 2009, 21:21
Hi shmia,

sorry, dass ich noch nicht geantwortet habe, aber mein Rechner ist diese Woche abgeka... Da hatte ich etwas Stress. Das Thema Frames ist mir leider etwas unsympathisch geworden. Ich habe eigentlich fast nie mit Frames gearbeitet, außer in einem Projekt vor ca. einem Jahr. Das hat mir die Laune an Frames echt verhagelt.
Das was du vorstellst ist nicht schlecht, aber für eine Umstellung ist der Code etwas zu weit bei mir.

Da ich im Moment denke, dass ich mit den Packages nun erst mal nichts mehr falsch mache (hoffe ich zumindest) möchte ich schon raus bekommen, was da beim laden schief läuft.
Ich teste mal weiter. Dank für deine Mühe,

Gruß oki
42
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#7

Re: RuntimePackage laden/verwenden

  Alt 19. Mär 2009, 09:27
Hi Leute,

das war ein Kampf. Hab den Fehler gefunden!

Mit den Packages und deren Umgang ist alles korrekt. Der Fehler war an einer anderen Stelle. In meinen Units waren die Zeilenumbrüche nicht korrekt. Mann will es kaum glauben. Nachdem ich den Fehler auf drei anderen Rechnern mit unterschiedlicher Delphi-Installation nachvollziehen konnte hab ich mir die Mühe gemacht und mir meine Units mit einem HEX-Editor angeschaut. Mein Verdacht waren versteckte "Steuerzeichen". Dabei habe ich ein $0D$0D sowie ein einzelnes $0D anstatt eines $0D$0A als Zeilenumbruch gefunden. Nachdem ich dies geändert hatte (im Hexeditor) war alles Bestens. Der Versatz war weg, die Programme und Runtimepackages laufen zur vollsten Zufriedenheit. Debuggen: bestens.

Wie dieser Fehler da rein kam ist mir aber immer noch ein Rätzel. Ich habe die Units ausschließlich mit Delphi geöffnet. Auch CodeGear hat darauf noch keine Antwort gegeben. Ich glaube zu wissen, dass bei HTML und Linux $0D als Zeilenumbruch verwendet wird. Habe den verwendeten Code aber definitiv selber geschrieben und nicht irgendwo her kopiert. Das einzige, was ich zwischendurch gemacht habe waren mehrere Refactorings. Ich hoffe nicht, dass da der Fehler steckt.

Wer diesen Fehler hat und zu faul ist das mit einem Hex-Editor zu machen, der kann die Unit auch in einem einfachen Texteditor laden und wieder speichern. Das sollte diese Fehler automatisch korrigieren. Ich hatte mir erst ein kleines eigenes Tool geschrieben in dem ich meine Units in ein Memo lade. Dort wollte ich dann entsprechende Such- und Korrigiermethoden implementieren. Dabei habe ich festgestellt, dass das Memo die benannten Fehler automatisch korrigiert. Ich brauchte die Unit dann nur noch unter dem gleichen Namen speichern und alles war paletti.

Dann schönen Gruß,

oki
42
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:02 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz