unituntDllManager;
Schnittstelle
verwendet
Windows, Klassen, SysUtils, Forms;
Typ
EDllError=Class(Exception);
TDllClass=ClassofTDll;
TDll=Klasse;
TDllEvent=procedure(Sender:TObject;ADll:TDll)ofObject;
{TDllManager
o提供对Dll的管理功能;
oAdd时自动创建TDll对象,但不尝试装载;
oDelete时自动销毁TDll对象;
}
TDllManager=Klasse(TList)
Privat
FLock:TRTLCriticalSection;
FDllClass:TDllClass;
FOnDllLoad:TDllEvent;
FOnDllBeforeUnLoaded:TDllEvent;
functionGetDlls(constIndex:Integer):TDll;
functionGetDllsByName(constFileName:String):TDll;
geschützt
procedureNotify(Ptr:Pointer;Action:TListNotification);override;
öffentlich
KonstruktorCreate;
destructorDestroy;override;
functionAdd(constFileName:String):Integer;overload;
functionIndexOf(constFileName:String):Integer;overload;
functionRemove(constFileName:String):Integer;overload;
procedureLock;
procedureUnLock;
propertyDllClass:TDllClassreadFDllClasswriteFDllClass;
propertyDlls[constIndex:Integer]:TDllreadGetDlls;default;
propertyDllsByName[constFileName:String]:TDllreadGetDllsByName;
propertyOnDllLoaded:TDllEventreadFOnDllLoadwriteFOnDllLoad;
propertyOnDllBeforeUnLoaded:TDllEventreadFOnDllBeforeUnLoadedwriteFOnDllBeforeUnLoaded;
Ende;
{TDll
o代表一个Dll,Windows.HModule
o销毁时自动在Eigentümer中删除自身;
o Die Funktion „overrideDoDllLoaded“ oder „DoDllUnLoaded“ ist die beste Option;
}
TDll=Klasse(TObject)
Privat
Besitzer:TDllManager;
FModule:HMODULE;
FFileName:String;
FPermit:Boolean;
procedureSetFileName(constValue:String);
functionGetLoaded:Boolean;
procedureSetLoaded(constValue:Boolean);
procedureSetPermit(constValue:Boolean);
geschützt
procedureDoDllLoaded;virtual;
procedureDoBeforeDllUnLoaded;virtual;
procedureDoDllUnLoaded;virtual;
procedureDoFileNameChange;virtual;
procedureDoPermitChange;virtual;
öffentlich
KonstruktorCreate;virtuell;
destructorDestroy;override;
functionGetProcAddress(constOrder:Longint):FARPROC;overload;
functionGetProcAddress(constProcName:String):FARPROC;overload;
propertyFileName:StringreadFFileNamewriteSetFileName;
propertyLoaded:BooleanreadGetLoadedwriteSetLoaded;
propertyOwner:TDllManagerreadFOwner;
propertyPermit:BooleanreadFPermitwriteSetPermit;
Ende;
Durchführung
{TDll}
KonstruktorTDll.Create;
beginnen
Besitzer:=nil;
FFileName:=´´;
FModule:=0;
FPermit:=True;
Ende;
destructorTDll.Destroy;
var
Manager:TDllManager;
beginnen
Geladen:=False;
ifFOwner<>nilthen
beginnen
//在拥有者中删除自身
Manager:=FOwner;
//未防止在TDllManager中重复删除,因此需要将
//FOwner设置为nil;<--此段代码和TDllManager.Notify需要配合
//才能确保正确。
Besitzer:=nil;
Manager.Remove(Selbst);
Ende;
geerbt;
Ende;
functionTDll.GetLoaded:Boolean;
beginnen
result:=FModule<>0;
Ende;
functionTDll.GetProcAddress(constOrder:Longint):FARPROC;
beginnen
ifLoadedthen
result:=Windows.GetProcAddress(FModule,Pointer(Order))
anders
raiseEDllError.CreateFmt(´DoLoadbeforeGetProcAddressof%u´,[DWORD(Order)]);
Ende;
functionTDll.GetProcAddress(constProcName:String):FARPROC;
beginnen
ifLoadedthen
result:=Windows.GetProcAddress(FModule,PChar(ProcName))
anders
raiseEDllError.CreateFmt(´DoLoadbeforeGetProcAddressof%s´,[ProcName]);
Ende;
procedureTDll.SetLoaded(constValue:Boolean);
beginnen
ifLoaded<>Valuethen
beginnen
ifnotValuethen
beginnen
Assert(FModule<>0);
DoBeforeDllUnLoaded;
versuchen
FreeLibrary(FModule);
FModule:=0;
außer
Application.HandleException(Self);
Ende;
DoDllUnLoaded;
Ende
anders
beginnen
FModule:=LoadLibrary(PChar(FFileName));
versuchen
Win32Check(FModule<>0);
DoDllLoaded;
außer
OnE:Exceptiondo
beginnen
ifFModule<>0then
beginnen
FreeLibrary(FModule);
FModule:=0;
Ende;
raiseEDllError.CreateFmt(´LoadLibraryError:%s´,[E.Message]);
Ende;
Ende;
Ende;
Ende;
Ende;
procedureTDll.SetFileName(constValue:String);
beginnen
ifLoadedthen
raiseEDllError.CreateFmt(´DoUnloadbeforeloadanotherModulenamed:%s´,
[Wert]);
ifFFileName<>Valuethen
beginnen
FFileName:=Wert;
DoFileNameChange;
Ende;
Ende;
procedureTDll.DoFileNameChange;
beginnen
//dononthing.
Ende;
procedureTDll.DoDllLoaded;
beginnen
ifAssigned(FOwner)andAssigned(FOwner.OnDllLoaded)then
FOwner.OnDllLoaded(FOwner,Self);
Ende;
procedureTDll.DoDllUnLoaded;
beginnen
//dononthing.
Ende;
procedureTDll.DoPermitChange;
beginnen
//dononthing.
Ende;
procedureTDll.SetPermit(constValue:Boolean);
beginnen
ifFPermit<>Valuethen
beginnen
FPermit:=Wert;
DoPermitChange;
Ende;
Ende;
procedureTDll.DoBeforeDllUnLoaded;
beginnen
ifAssigned(FOwner)andAssigned(FOwner.OnDllBeforeUnLoaded)then
FOwner.OnDllBeforeUnLoaded(FOwner,Self);
Ende;
{TDllManager}
functionTDllManager.Add(constFileName:String):Integer;
var
Dll:TDll;
beginnen
Ergebnis:=-1;
Sperren;
versuchen
ifDllsByName[FileName]=nilthen
beginnen
Dll:=FDllClass.Create;
Dll.FileName:=FileName;
result:=Add(Dll);
Ende
anders
Ergebnis:=-1;
Endlich
Entsperren;
Ende;
Ende;
KonstruktorTDllManager.Create;
beginnen
FDllClass:=TDll;
InitializeCriticalSection(FLock);
Ende;
destructorTDllManager.Destroy;
beginnen
DeleteCriticalSection(FLock);
geerbt;
Ende;
functionTDllManager.GetDlls(constIndex:Integer):TDll;
beginnen
Sperren;
versuchen
if(Index>=0)and(Index<=Count-1)then
Ergebnis:=Elemente[Index]
anders
raiseEDllError.CreateFmt(´ErrorIndexofGetDlls,Value:%d,TotalCount:%d´,[Index,Count]);
Endlich
Entsperren;
Ende;
Ende;
functionTDllManager.GetDllsByName(constFileName:String):TDll;
var
I:Integer;
beginnen
Sperren;
versuchen
I:=IndexOf(FileName);
wennI>=0dann
result:=Dlls[I]
anders
Ergebnis:=nil;
Endlich
Entsperren;
Ende;
Ende;
functionTDllManager.IndexOf(constFileName:String):Integer;
var
I:Integer;
beginnen
Ergebnis:=-1;
Sperren;
versuchen
forI:=0toCount-1do
ifCompareText(FileName,Dlls[I].FileName)=0then
beginnen
Ergebnis:=I;
brechen;
Ende;
Endlich
Entsperren;
Ende;
Ende;
procedureTDllManager.Lock;
beginnen
OutputDebugString(Pchar(´TRLockDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));
EnterCriticalSection(FLock);
OutputDebugString(Pchar(´LockedDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));
Ende;
procedureTDllManager.Notify(Ptr:Pointer;Action:TListNotification);
beginnen
ifAction=lnDeletedthen
beginnen
//若TDll(Ptr).Owner和Self不同,则
//表明由TDll.Destroy触发;
ifTDll(Ptr).Owner=Selfthen
beginnen
//防止FOwner设置为nil之后相关事件不能触发
TDll(Ptr).DoBeforeDllUnLoaded;
TDll(Ptr).FOwner:=nil;
TDll(Ptr).Free;
Ende;
Ende
anders
ifAction=lnAddedthen
TDll(Ptr).FOwner:=Self;
geerbt;
Ende;
functionTDllManager.Remove(constFileName:String):Integer;
var
I:Integer;
beginnen
Ergebnis:=-1;
Sperren;
versuchen
I:=IndexOf(FileName);
wennI>=0dann
result:=Remove(Dlls[I])
anders
Ergebnis:=-1;
Endlich
Entsperren;
Ende;
Ende;
procedureTDllManager.UnLock;
beginnen
LeaveCriticalSection(FLock);
OutputDebugString(Pchar(´UnLockDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));
Ende;
Ende.