![]() |
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:
Danke im Voraus
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; |
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:
Und hier der Pseudo-Code vom Hauptprogramm
//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
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 |
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? |
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. |
Re: FreeLibrary in OnCloseQuery verursacht AV
Zitat:
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 ( ![]() Was soll ich nun tun? PS: Schönes Beispiel - aber mit extremen Weitsprung hatte ich noch nie was am Hut :wink: |
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. |
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. |
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? |
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:
Dll:
//LadePluginDLL
PluginDLL_YourID(EineID);
Delphi-Quellcode:
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)
procedure PluginDLL_YourID(EineID);
begin GPluginID := EineID; end; [...] PostMessage(Haupprogramm_Handle, MessageID, GPluginID, 0); |
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. |
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