Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Zeos-Components, PlugIn-DLL-Forms und AV (https://www.delphipraxis.net/124096-zeos-components-plugin-dll-forms-und-av.html)

TheMiller 14. Nov 2008 09:16


Zeos-Components, PlugIn-DLL-Forms und AV
 
Hallo,

erstmal sorry für den blöden Titel. Mir fiel kein besserer ein. Wenn ihr mein Problem lesen solltet, dann könnt ihr es hoffentlich nachvollziehen.

Los geht's:

Ich habe eine Applikation geschrieben, die aus Hauptprogramm und Plug-Ins (DLL-Forms) besteht. Diese werden, je nach Bedarf dynamisch geladen. Das funktioniert soweit auch super!

HauptAnwendung stellt für den Benutzerlogin eine Verbindung zu MySQL via Zeos-DBO her. Die PlugIns beim Laden und benutzen stellen über ihre eigene Zeos-Komponente eine neue Verbindung her.

Nach jedem Öffnen einer Verbindung, wie diese nach Erhalt oder Senden der Daten wieder geschlossen.

Gut. Soweit die Konstellation. Jetzt zum Problem:

Wenn ich mich nun im Hauptprogramm einlogge und dann ein PlugIn bediene, funktioniert alles einwandtfrei.

Wenn ich mich aber nicht einlogge und dann ein Plugin bediene, welche seinerseits eine Verbindung zur DB herstellt, kommt beim Beenden des Programms die Meldung: "Zu viele aufeinanderfolgende Exceptions...". Das Programm wird NICHT beendet. Also nicht vollständig jedenfalls.

Dieser Fehler tritt nur auf, wenn ich mich NICHT eingeloggt habe. Da das Programm noch im Anfangsstadium ist, hat der Login noch nichts zu sagen. Er kontrolliert noch nichts.

Aber das zeigt mir, dass irgendwo ein böser (Speicher)Fehler steckt. FastMM sagt beim Beenden, wenn ich micht nicht eingeloggt habe folgendes:

Zitat:

Zitat von FastMM4
13 - 20 bytes: EAccessViolation x 1, Unkown x 2
21 - 28 bytes: String x 6
101 - 116 bytes: String x 1
453 - 500 bytes: TZMyMSQLNativeLibraryLoader x 2

Wenn ich mich vorher "eingeloggt" habe, kommt keine Meldung von Zeos.

Nochmal ganz kurz:
Das einloggen hat (noch) nichts zu bedeuten. Es stellt nur Verbindung von der MainApp zur DB her, prüft Username und PW und sagt "Hallo [Username]". Aber wenn das passiert, dann funktionieren auch die PlugIns. Wenn nicht, dann kommt die o.g Meldung.

Bitte, kann mir jmd. Tipps, Hilfe oder Lösungsansätze geben?
Ich verstehe diesen Fehler nicht.

Danke und Grüße!

TheMiller 15. Nov 2008 12:09

Re: Zeos-Components, PlugIn-DLL-Forms und AV
 
*push*

Hat niemand nicht vielleicht einen Tipp, wie ich näher an die Fehlerursache komme? Es gibt meinerseits keinen Fortschritt...

blawen 15. Nov 2008 12:22

Re: Zeos-Components, PlugIn-DLL-Forms und AV
 
Wenn ich mir so Deine Beschreibung lese, komme ich in die Versuchung meine verstaube Glaskugel rauszusuchen. Anderen wird es vermutlich ähnlich gehen.

Kannst Du ev. relevanten Code, in Form eines Beispiels, posten, bei welchem der Fehler nachvollzogen werden kann? Ich denke, dass Dir so viel eher geholfen werden kann.

RWarnecke 15. Nov 2008 12:30

Re: Zeos-Components, PlugIn-DLL-Forms und AV
 
Und wie stellen die DLL die Verbindung zur Datenbank her ? Woher bekommen diese den Usernamen und das Passwort ?

Edit: Ich denke, dass die PlugIn's auf den Login von der Hauptanwendung aufbauen. Ansonsten weiß ich auch nicht mehr :glaskugel:

TheMiller 15. Nov 2008 12:45

Re: Zeos-Components, PlugIn-DLL-Forms und AV
 
Hallo,

also, die DLL-Plugins haben eine eigene Zeos-Komponente im Formular. In dieser habe ich den Usernamen, pw etc. eingetragen. Genau wie in der MainApp. Diese hat auch eine Zeos-Komponente... Stören die sich?

Ich poste nochmal ein bissl code...moment..

Folgendes Prinzip: Bei Programmstart werden alle PlugIns gesucht, geladen, Menüeinträge erstellt und wieder entladen, damit sie den Speicher nicht zumüllen. Diese Prozedur habe ich auch in anderen Anwendungen benutzt. Daran sollte es nicht liegen:

Delphi-Quellcode:
procedure TForm1.LoadPlugIn(FileName: String);
var
  TempHandle: Cardinal;
  ProcAddr: Pointer;
  LoadPlugInProc: TLadePlugIn;
  TempPlugIn: TProJurisPlugIn;
  Buffer: PChar;
  len: Integer;
  appkey, titel: String;
  addToWrapper: boolean;
  i: Integer;
  Item: TTreeNode;
begin
  TempHandle:=0;
  //Läd PlugIn und schreibt Menü-Eintrag
  TempHandle:=LoadLibrary(PChar(Filename));
  if (TempHandle <> INVALID_HANDLE_VALUE) and (TempHandle <> 0) then
  begin
    ProcAddr:=GetProcAddress(Temphandle, 'LadePlugIn');

    if (ProcAddr = nil) then
    begin
      FreeLibrary(TempHandle);
      MessageDLG('Die Datei '+Filename+' ist kein gültiges PlugIn', mtError, [mbOK], 0);
      Exit;
    end;

    LoadPlugInProc:=TLadePlugIn(ProcAddr);
    try
      TempPlugIn:=Nil;
      LoadPlugInProc(Application.Handle, TempPlugin);
    except
      FreeLibrary(TempHandle);
      MessageDLG('Die Datei '+Filename+' ist kein gültiges PlugIn', mtError, [mbOK], 0);
    end;

    if (TempPlugIn <> nil) then
    begin
      //Appkey holen
      len:=TempPlugin.GetAppKey(nil, 0);
      try
        GetMem(Buffer, len+1);
        len:=TempPlugIn.GetAppKey(Buffer, len+1);
        appkey:=Buffer;
      finally
        FreeMem(Buffer);
      end;

      //Titel holen
      len:=TempPlugin.GetTitel(nil, 0);
      try
        GetMem(Buffer, len+1);
        len:=TempPlugIn.GetTitel(Buffer, len+1);
        titel:=Buffer;
      finally
        FreeMem(Buffer);
      end;

      if (appkey = 'PI-3') then
      begin
        SetLength(PlugIns, Succ(Length(PlugIns)));
        PlugIns[High(PlugIns)].PlugInTitel:=titel;
        PlugIns[High(PlugIns)].PlugInFile:=FileName;
        PlugIns[High(PlugIns)].PlugInName:=TempPlugIn;
        PlugIns[High(PlugIns)].PlugInHandle:=TempHandle;

        //PlugIns[High(PlugIns)].PlugInVersion:=GetVersion(FileName);
        PlugIns[High(PlugIns)].PlugInName.InitPlugIn;
        PlugIns[High(PlugIns)].PlugInName.TransmitHandle(self.Handle);

        // Wird das PlugIn zum ersten mal geladen?
        AddToWrapper:=True;
        for i:=0 to High(PlugInWrapper) do
        begin
          if (PlugInWrapper[i].PlugInTitel = titel) then
          begin
            addToWrapper:=false;
            Exit
          end;
        end;

        if (addToWrapper) then
        begin
          Item:=TreeView1.Items.AddChild(TreeView1.Items.GetFirstNode, titel);
          SetLength(PlugInWrapper, Succ(Length(PlugInWrapper)));
          PlugInWrapper[High(PlugInWrapper)].PlugInTitel:=titel;
          PlugInWrapper[High(PlugInWrapper)].PlugInFile:=FileName;
        end;

      UnloadPlugIns;
      FreeLibrary(TempHandle);

      end else
      begin
        MessageDLG('Das Plugin ('+filename+') ist nicht mit der Programmversion kompatibel.', mtError, [mbOK], 0);
      end;

    end else
    begin
      MessageDLG('Die Datei '+Filename+' ist kein gültiges PlugIn', mtError, [mbOK], 0);
    end;

  end else
  begin
    MessageDLG('Die Datei '+Filename+' ist kein gültiges PlugIn', mtError, [mbOK], 0);
  end;
  TempPlugIn:=nil;
end;
Hier wird das PlugIn geladen und INNERHALB der MainApp auf Panel1 angezeigt:

Delphi-Quellcode:
procedure TForm1.RunPlugIn(Sender: TObject);
var
  i,j: Integer;
  s: String;
  hndl: Integer;
  sl:TStringList;
begin
  UnloadPlugins;
  s:=TTreeNode(Sender).Text;
 
  for i:=0 to high(PlugInWrapper) do
  begin
    if (s = PlugInWrapper[i].PlugInTitel) then
    begin
      LoadPlugIn(PlugInWrapper[i].PlugInFile);
      hndl:=PlugIns[High(PlugIns)].PlugInName.SendFormHandle;
      PlugInActive:=hndl;
      Windows.SetParent(hndl, Panel1.Handle);
      SetWindowPos(hndl, hwnd_top, -5, -25, 0, 0, SWP_NOSIZE);
      PlugIns[High(PlugIns)].PlugInName.Execute;
    end;
  end;
end;
Das ist mein Login in der MainApp:

Delphi-Quellcode:
 if (Key = #13) then
  begin
    if not (Form1.ZConnection1.Connected) then
      Form1.ZConnection1.Connect;


    if (Form1.ZConnection1.Connected) then
    begin
      Form1.ZQuery1.SQL.Text:='SELECT * FROM benutzer WHERE username = '''+Edit1.Text+''' AND passwort = '''+MD5Print(MD5String(MaskEdit1.Text))+''';';
      Form1.ZQuery1.Open;
      if (Form1.ZQuery1.RecordCount > 0) then
      begin
        username:=Form1.ZQuery1.FieldByName('username').AsString;
        uid:=Form1.ZQuery1.FieldByName('uid').AsInteger;
        loggedin:=True;

        Label2.Caption:='Angemeldet als '+username;

        Label3.Hide;
        Label4.Hide;
        Edit1.Hide;
        MaskEdit1.Hide;

        Windows.SetParent(Form2.Handle, Panel1.Handle);
        SetWindowPos(Form2.Handle, hwnd_top, 0, 0, 0, 0, SWP_NOSIZE);

        Form2.Label5.Caption:='Guten Tag '+username+',';
        Form2.Show;

      end else
      begin
        MessageDLG('Die Benutzerdaten sind nicht korrekt', mtInformation, [mbOK], 0);
      end;
    end;

  end;
  Form1.ZQuery1.Close;
end;
Und das ist die Prozedur, die ausgeführt wird, wenn das Plugin vom User geöffnet wird. Das wird nicht beim Starten ausgeführt, wenn die MainApp die PlugIns einliest:

Delphi-Quellcode:
procedure TForm1.StartUp;
var
  Tab: TTabSheet;
begin
  if not (Connection1.Connected) then
  begin
    Connection1.Connect; //Wenn MainApp Connected!
  end;

  Form1.Query1.SQL.Text:='SELECT realname FROM benutzer WHERE rang = 2 ORDER BY uid ASC;';
  Form1.Query1.Open;
  while not (Form1.Query1.Eof) do
  begin
    Tab:=TTabSheet.Create(PageControl1);
    Tab.Caption:='Hallo';
    Form1.Query1.Next;
  end;
  Form1.Query1.Close;
  Connection1.Disconnect;

end;
So, das ist so ziemlich alles an Code, was es bisher gibt.

Nochmal kurze Erklärung:

Einloggen in MainApp -> PlugIn öffnen -> Programm beendet ohne Fehler
kein Einloggen in MainApp -> PlugIn öffnen -> zu viele aufeinanderfolgende Exceptions (siehe FastMM)

Dabei hat der Login keinerlei Bezug zum Plugin und umgekehrt. Daher muss es was Speichertechnisches sein...

Danke

TheMiller 16. Nov 2008 19:38

Re: Zeos-Components, PlugIn-DLL-Forms und AV
 
Hat keiner eine Idee, wie solch ein Fehler zu Stande kommt?

Danke


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:09 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