Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi FreeLibrary in OnCloseQuery verursacht AV (https://www.delphipraxis.net/95219-freelibrary-onclosequery-verursacht-av.html)

TheMiller 3. Jul 2007 12:21


FreeLibrary in OnCloseQuery verursacht AV
 
Hallo Leute,

ich habe ein PlugIn-System. Diese PlugIns sind DLLs mit Formulare. Wenn nun ein PlugIn durch den User geschlossen oder auf das "X" gedrückt wird, wird eine Message an das Hauptprogramm gesendet (WM_COPYDATA) und das entsprechende PlugIn freigegeben, indem erst die erstellten Forms freigebenen und dann die DLL mit FreeLibrary geschlossen wird.

Das klappt soweit auch ganz gut. Nun möchte ich, dass die DLL auch dann freigegeben wird, wenn der User auf das "X" klickt. Also habe ich den entsprechenden Quelltext (siehe unten) in die OnCloseQuery kopiert. Aber immer, wenn dieses Event eintritt, gibt es eine AV. Ich kann auch nicht sehen, an welcher Stelle sie auftritt. Aber mit dem PlugIn hat es nichts zu tun. Vielleicht habe ich auch nur einen logischen Denkfehler, denn sonst funktioniert das Freigeben - nur eben nicht in der OnCloseQuery.

Hier der Quelltext:

Delphi-Quellcode:
var
  Ident: PIdent;
  cds: TCopyDataStruct;
  hWnd: THandle;
begin
  GetMem(Ident, SizeOf(TIdent));
  try
    ident.appname:='Config';
    cds.dwData:=0;
    cds.cbData:=sizeOf(TIdent);
    cds.lpData:=Ident;
    hWnd:=FindWindow(nil, 'Hauptmenu');
    SendMessage(hWnd, WM_COPYDATA, Handle, Integer(@cds));
  finally
   FreeMem(Ident, sizeof(TIdent));
  end;
Danke im Voraus

SirThornberry 3. Jul 2007 12:58

Re: FreeLibrary in OnCloseQuery verursacht AV
 
:shock: Du sendest mit SendMessage eine Nachricht an das Hauptprogramm was daraufhin die DLL frei gibt?
Das kann doch nur schief gehen. Hier mal Pseudo-Code aus der DLL was da passiert:
Delphi-Quellcode:
//do Andything
SendMessage(Handle_Hauptprogramm, YourMessageID, X, y);
//Jetzt wird an der Stelle im Code weitergemacht aber das geht ja nicht wenn der Speicherbereich (wo der Code gerade abgearbeitet wird) nicht mehr zum Prozess gehört sondern frei gegeben wurde
Und hier der Pseudo-Code vom Hauptprogramm
Delphi-Quellcode:
procedure TYourClass.YourMsgProc(var AMsg: TMessage);
begin
  //Dll Frei geben
end; //Mit/Nach dem End wird dort hinn zurück gesprungen von wo aufgerufen wurde (wo also das SendMessage steht) und das ist die dll. Also wird versucht dorthin im Speicher zu springen wo man gar nicht mehr hinn darf weil der Speicherbereich nicht mehr zu Programm gehört

TheMiller 3. Jul 2007 13:07

Re: FreeLibrary in OnCloseQuery verursacht AV
 
Na klar geht das. Wenn ich im PlugIn einem Button diesen Code gebe und ihn dann klicke, funktioniert das einwandtfrei. Die DLL wird einfach freigegeben. Keine Fehler!

Oder gibt es eine andere Methode, wie ich dem Hauptprogramm sagen kann, dass es eine DLL freigeben kann, wenn der User die DLL nicht mehr benutzt?

SirThornberry 3. Jul 2007 13:14

Re: FreeLibrary in OnCloseQuery verursacht AV
 
du solltest an das Hauptprogramm eine Message posten um sicherzustellen das der Aufruf nicht von Seiten der DLL kommt.
Und wenn es mit einem Buttonklick funktioniert nenne ich das einfach nur Glück (oder mein Veständnis der Internas ist völlig falsch).

Du kannst dir das in etwas so vorstellen: Du sitzt in einem Zug und der Schaffner sagt dir du sollst vor in den Triebwagen, von dort aus die anderen Wagen abhängen und wenn diese abhgehängt sind sollst du zurück in die Wagen kommen. Zugegeben, das könnte sogar noch klappen mit einem Sprung weil die Wagen sich nicht in Luft auflösen. Werden die Wagen vom Triebwagen aus aber gesprengt würdest du ins Leere springen.

TheMiller 3. Jul 2007 13:24

Re: FreeLibrary in OnCloseQuery verursacht AV
 
Zitat:

Zitat von SirThornberry
du solltest an das Hauptprogramm eine Message posten um sicherzustellen das der Aufruf nicht von Seiten der DLL kommt

Ok... von wo aus soll ich denn diese Message posten? Hier mal mein Szenario:

Hauptmenu ist das Hauptprogramm
Config ist ein PlugIn

Ein User öffnet jetzt das Config-PlugIn und speichert die Einstellungen. Es war immer so, dass die Einstellungen gespeichert wurden und das PlugIn sich versteckt (Self.Hide).

Doch mit mehreren PlugIns kommt es schonmal vor, dass der Speicher ziemlich ausgelastet wird (20-40MB). Daher möchte ich, dass die DLL freigegeben wird.

Deshalb habe ich von der DLL aus eine Message geschrieben, die zum Freigeben der DLL in der Hauptanwendung führt. Die Idee kam zwar von mir, aber in einem anderen Thread (http://www.delphipraxis.net/internal...ghlight=DJ-SPM) sagte man mir, dass das ginge...

Was soll ich nun tun?

PS: Schönes Beispiel - aber mit extremen Weitsprung hatte ich noch nie was am Hut :wink:

TheMiller 3. Jul 2007 13:36

Re: FreeLibrary in OnCloseQuery verursacht AV
 
OK...

Das mit dem Klick auf den Button war doch nur Glück... (wenigstens hatte ich jetzt mal wieder Glück *g*)

Ne Spaß bei Seite! Bin ratlos... muss doch irgendwie gehen.

Also, wollte nur bescheid sagen, dass das doch nicht geht.

SirThornberry 3. Jul 2007 13:37

Re: FreeLibrary in OnCloseQuery verursacht AV
 
ich hab es grad auch mal mit einem Button probiert und den Stack etc. beobachtet. Und meine Vermutung war richtig. Es wird zurück an die Adresse gesprungen wo die DLL war und dann macht es "bumm". Dein PostMessage kann an der gleichen Stelle dann stehen wie das SendMessage. Da aber eben die Message gepostet wird und somit erst abgearbeitet wird wenn die Nachrichtenschleife im Hauptprogramm diese erhält passiert nichts weil zu dem Zeitpunkt nichts aus dem Speicherbereich der DLL abgearbeitet wird.

(habs auch in meinem Testprojekt probiert. Sobald SendMessage durch PostMessage ersetzt wird klappt es da dann ja nicht zurück in den DLL Adressraum gesprungen wird)

Mit PostMessage funktioniert wm_copydata dann natürlich nicht mehr.

TheMiller 3. Jul 2007 13:42

Re: FreeLibrary in OnCloseQuery verursacht AV
 
Gut, dann habe ich eine Frage:

ich habe ja mehrere PlugIns. Wie kann ich dann im Hauptprogramm ermitteln, aus welchem PlugIn die Message kam, damit ich das richtige PlugIn freigeben kann. Aus diesem Grund habe ich ja WM_COPYDATA benutzt. Hast du noch eine Idee?

SirThornberry 3. Jul 2007 13:48

Re: FreeLibrary in OnCloseQuery verursacht AV
 
aus irgendeinem Grund kann dein Programm ja mit "Config" was anfangen, weiß also welches Plugin das "Config" ist. Genauso kannst du auch mit ID's arbeiten. Oder du übergibst der DLL einen Pointer auf die Plugindaten welchen sie dann Postet

Hauptprogramm:
Delphi-Quellcode:
//LadePluginDLL
PluginDLL_YourID(EineID);
Dll:
Delphi-Quellcode:
procedure PluginDLL_YourID(EineID);
begin
  GPluginID := EineID;
end;

[...]
PostMessage(Haupprogramm_Handle, MessageID, GPluginID, 0);
ebenso kannst du als ID auch das InstanzHandle der DLL verwenden was dir LoadLibrary zurück gibt. (diese ID müsstest du nichtmal übergeben weil die dll das selbst ermitteln kann welches HINSTANCE sie hat)

TheMiller 3. Jul 2007 13:57

Re: FreeLibrary in OnCloseQuery verursacht AV
 
Achso... also kann ich diesen wParam-Parameter selbst belegen. Praktisch ein Platzhalte für selbstdefinierte Integer-Parameter. Wenn ich das so richtig verstanden habe, dann ist das ja cool.

Was ist lParam für ein "Platzhalter"?


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:07 Uhr.
Seite 1 von 2  1 2      

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