unidaduntDllManager;
interfaz
usos
Windows, Clases, SysUtils, Formularios;
tipo
EDllError=Clase(Excepción);
TDllClass=ClasedeTDll;
TDll=Clase;
TDllEvent=procedimiento(Remitente:TObject;ADll:TDll)ofObject;
{TDllManager
o提供对Dll的管理功能;
oAdd时自动创建TDll对象,但不尝试装载;
oDelete时自动销毁TDll对象;
}
TDllManager=Clase(TLista)
privado
FLock:TRTLCriticalSection;
Clase FDll: Clase TDll;
FOnDllLoad:TDllEvent;
FOnDllBeforeUnLoaded:TDllEvent;
funciónGetDlls(constIndex:Integer):TDll;
functionGetDllsByName(constFileName:String):TDll;
protegido
procedimientoNotify(Ptr:Pointer;Action:TListNotification);override;
público
constructorCrear;
destructorDestroy;anular;
functionAdd(constFileName:String):Entero;sobrecarga;
functionIndexOf(constFileName:String):Entero;sobrecarga;
funciónRemove(constFileName:String):Entero;sobrecarga;
procedimientoBloqueo;
procedimientoDesbloquear;
propiedadDllClass:TDllClassreadFDllClasswriteFDllClass;
propiedadDlls[constIndex:Integer]:TDllreadGetDlls;predeterminado;
propiedadDllsByName[constFileName:String]:TDllreadGetDllsByName;
propiedadOnDllLoaded:TDllEventreadFOnDllLoadwriteFOnDllLoad;
propiedadOnDllBeforeUnLoaded:TDllEventreadFOnDllBeforeUnLoadedwriteFOnDllBeforeUnLoaded;
fin;
{TDll
o 代表一个Dll,Windows.HMódulo
o销毁时自动在Propietario中删除自身;
o子类可通过覆盖overrideDoDllLoaded,以及DoDllUnLoaded进行功能扩展;
}
TDll=Clase(TObjeto)
privado
Propietario: TDllManager;
Módulo F: HMÓDULO;
FFileName:Cadena;
FPermiso: booleano;
procedimientoSetFileName(constValue:String);
funciónGetLoaded:Booleano;
procedimientoSetLoaded(constValue:Boolean);
procedimientoSetPermit(constValue:Boolean);
protegido
procedimientoDoDllLoaded;virtual;
procedimientoDoBeforeDllUnLoaded;virtual;
procedimientoDoDllUnLoaded;virtual;
procedimientoDoFileNameChange;virtual;
procedimientoDoPermitChange;virtual;
público
constructorCrear;virtual;
destructorDestroy;anular;
functionGetProcAddress(constOrder:Longint):FARPROC;sobrecarga;
functionGetProcAddress(constProcName:String):FARPROC;sobrecarga;
propiedadFileName:StringreadFFileNamewriteSetFileName;
propiedadLoaded:BooleanreadGetLoadedwriteSetLoaded;
propiedadPropietario:TDllManagerreadFOwner;
propiedadPermit:BooleanreadFPermitwriteSetPermit;
fin;
implementación
{TDll}
constructorTDll.Create;
comenzar
Propietario:=nulo;
FFileName:=´´;
Módulo FM:=0;
FPermit:=Verdadero;
fin;
destructorTDll.Destroy;
var
Administrador:TDllManager;
comenzar
Cargado:=Falso;
ifFOwner<>nilthen
comenzar
//在拥有者中删除自身
Gerente:=FOpropietario;
//未防止在TDllManager中重复删除,因此需要将
//FOwner设置为nil;<--此段代码和TDllManager.Notify需要配合
//才能确保正确。
Propietario:=nulo;
Gerente.Remove(Self);
fin;
heredado;
fin;
funciónTDll.GetLoaded:Booleano;
comenzar
resultado:=FMódulo<>0;
fin;
funciónTDll.GetProcAddress(constOrder:Longint):FARPROC;
comenzar
si está cargado entonces
resultado:=Windows.GetProcAddress(FModule,Pointer(Orden))
demás
riseEDllError.CreateFmt(´DoLoadbeforeGetProcAddressof%u´,[DWORD(Orden)]);
fin;
functionTDll.GetProcAddress(constProcName:String):FARPROC;
comenzar
si está cargado entonces
resultado:=Windows.GetProcAddress(FModule,PChar(ProcName))
demás
riseEDllError.CreateFmt(´DoLoadbeforeGetProcAddressof%s´,[ProcName]);
fin;
procedimientoTDll.SetLoaded(constValue:Boolean);
comenzar
si está cargado <> valor entonces
comenzar
si no es valor entonces
comenzar
Afirmar(FMódulo<>0);
DoBeforeDllUnLoaded;
intentar
Biblioteca gratuita (FMódulo);
Módulo FM:=0;
excepto
Aplicación.HandleException (Self);
fin;
DoDllUnLoaded;
fin
demás
comenzar
FModule:=LoadLibrary(PChar(FFileName));
intentar
Win32Check(FMódulo<>0);
DoDll cargado;
excepto
OneE:Excepcióndo
comenzar
siFMódulo<>0entonces
comenzar
Biblioteca gratuita (FMódulo);
Módulo FM:=0;
fin;
riseEDllError.CreateFmt(´LoadLibraryError:%s´,[E.Message]);
fin;
fin;
fin;
fin;
fin;
procedimientoTDll.SetFileName(constValue:String);
comenzar
si está cargado entonces
riseEDllError.CreateFmt(´DoUnloadbeforeloadanotherModulenamed:%s´,
[Valor]);
siFFfileName<>Valorentonces
comenzar
FFileName:=Valor;
DoFileNameChange;
fin;
fin;
procedimientoTDll.DoFileNameChange;
comenzar
//no hacer nada.
fin;
procedimientoTDll.DoDllLoaded;
comenzar
si está asignado (FOwner) y asignado (FOwner.OnDllLoaded) entonces
FOwner.OnDllLoaded(FOwner,Self);
fin;
procedimientoTDll.DoDllUnLoaded;
comenzar
//no hacer nada.
fin;
procedimientoTDll.DoPermitChange;
comenzar
//no hacer nada.
fin;
procedimientoTDll.SetPermit(constValue:Boolean);
comenzar
ifFPermit<>Valorentonces
comenzar
FPermiso:=Valor;
DoPermitChange;
fin;
fin;
procedimientoTDll.DoBeforeDllUnLoaded;
comenzar
si está asignado (FOwner) y asignado (FOwner.OnDllBeforeUnLoaded) entonces
FOwner.OnDllBeforeUnLoaded(FOwner,Self);
fin;
{TDllManager}
functionTDllManager.Add(constFileName:String):Entero;
var
Dll:TDll;
comenzar
resultado:=-1;
Cerrar con llave;
intentar
ifDllsByName[NombreDeArchivo]=nilentonces
comenzar
Dll:=FDllClass.Create;
Dll.FileName:=FileName;
resultado:=Agregar(Dll);
fin
demás
resultado:=-1;
finalmente
Descubrir;
fin;
fin;
constructorTDllManager.Create;
comenzar
FDllClass:=TDll;
InicializarSecciónCrítica(FLock);
fin;
destructorTDllManager.Destroy;
comenzar
Eliminar sección crítica (FLock);
heredado;
fin;
funciónTDllManager.GetDlls(constIndex:Integer):TDll;
comenzar
Cerrar con llave;
intentar
si (Índice> = 0) y (Índice <= Cuenta-1) entonces
resultado:=Artículos[Índice]
demás
riseEDllError.CreateFmt(´ErrorIndexofGetDlls,Value:%d,TotalCount:%d´,[Index,Count]);
finalmente
Descubrir;
fin;
fin;
functionTDllManager.GetDllsByName(constFileName:String):TDll;
var
I:Entero;
comenzar
Cerrar con llave;
intentar
I:=IndexOf(NombreDeArchivo);
siI>=0entonces
resultado:=Dlls[I]
demás
resultado:=nulo;
finalmente
Descubrir;
fin;
fin;
functionTDllManager.IndexOf(constFileName:String):Entero;
var
I:Entero;
comenzar
resultado:=-1;
Cerrar con llave;
intentar
paraI:=0toCount-1do
ifCompareText(NombreDeArchivo,Dlls[I].NombreDeArchivo)=0entonces
comenzar
resultado:=yo;
romper;
fin;
finalmente
Descubrir;
fin;
fin;
procedimientoTDllManager.Lock;
comenzar
OutputDebugString(Pchar(´TRLockDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));
EnterCriticalSection(FLock);
OutputDebugString(Pchar(´LockedDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));
fin;
procedimientoTDllManager.Notify(Ptr:Pointer;Action:TListNotification);
comenzar
siAcción=lnDeletedentonces
comenzar
//若TDll(Ptr).Owner和Self不同,则
//表明由TDll.Destroy触发;
ifTDll(Ptr).Owner=Selfentonces
comenzar
//防止FOwner设置为nil之后相关事件不能触发
TDll(Ptr).DoBeforeDllUnLoaded;
TDll(Ptr).FOwner:=nil;
TDll(Ptr).Gratis;
fin;
fin
demás
siAcción=lnAgregadoentonces
TDll(Ptr).FOwner:=Self;
heredado;
fin;
functionTDllManager.Remove(constFileName:String):Integer;
var
I:Entero;
comenzar
resultado:=-1;
Cerrar con llave;
intentar
I:=IndexOf(NombreDeArchivo);
siI>=0entonces
resultado:=Eliminar(Dlls[I])
demás
resultado:=-1;
finalmente
Descubrir;
fin;
fin;
procedimientoTDllManager.UnLock;
comenzar
LeaveCriticalSection(FLock);
OutputDebugString(Pchar(´UnLockDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));
fin;
fin.