unituntDllManager;
interface
usa
Windows, Classes, SysUtils, Formulários;
tipo
EDllError=Classe(Exceção);
TDllClass=ClassofTDll;
TDll=Classe;
TDllEvent=procedure(Sender:TObject;ADll:TDll)ofObject;
{TDllManager
o提供对Dll的管理功能;
oAdd时自动创建TDll对象,但不尝试装载;
oDelete时自动销毁TDll对象;
}
TDllManager=Classe(TLista)
privado
FLock:TRTLCriticalSection;
FDllClass:TDllClass;
FOnDllLoad:TDllEvent;
FOnDllBeforeUnLoaded:TDllEvent;
functionGetDlls(constIndex:Integer):TDll;
functionGetDllsByName(constFileName:String):TDll;
protegido
procedimentoNotify(Ptr:Ponteiro;Ação:TListNotification);substituir;
público
construtorCriar;
destruidorDestruir;substituir;
functionAdd(constFileName:String):Integer;sobrecarga;
functionIndexOf(constFileName:String):Integer;sobrecarga;
functionRemove(constFileName:String):Integer;sobrecarga;
procedimentoLock;
procedimentoUnLock;
propertyDllClass:TDllClassreadFDllClasswriteFDllClass;
propertyDlls[constIndex:Integer]:TDllreadGetDlls;default;
propertyDllsByName[constFileName:String]:TDllreadGetDllsByName;
propertyOnDllLoaded:TDllEventreadFOnDllLoadwriteFOnDllLoad;
propriedadeOnDllBeforeUnLoaded:TDllEventreadFOnDllBeforeUnLoadedwriteFOnDllBeforeUnLoaded;
fim;
{TDll
o代表一个Dll,Windows.HModule
o销毁时自动在Proprietário中删除自身;
o子类可通过覆盖overrideDoDllLoaded, e DoDllUnLoaded进行功能扩展;
}
TDll=Classe(TObject)
privado
Proprietário:TDllManager;
FMódulo:HMÓDULO;
NomedoArquivo:String;
FPermit:Booleano;
procedimentoSetFileName(constValue:String);
functionGetLoaded:Boolean;
procedimentoSetLoaded(constValue:Boolean);
procedimentoSetPermit(constValue:Boolean);
protegido
procedimentoDoDllLoaded;virtual;
procedimentoDoBeforeDllUnLoaded;virtual;
procedimentoDoDllUnLoaded;virtual;
procedimentoDoFileNameChange;virtual;
procedimentoDoPermitChange;virtual;
público
construtorCriar;virtual;
destruidorDestruir;substituir;
functionGetProcAddress(constOrder:Longint):FARPROC;sobrecarga;
functionGetProcAddress(constProcName:String):FARPROC;sobrecarga;
propertyFileName:StringreadFFileNamewriteSetFileName;
propertyLoaded:BooleanreadGetLoadedwriteSetLoaded;
propriedadeOwner:TDllManagerreadFOwner;
propertyPermit:BooleanreadFPermitwriteSetPermit;
fim;
implementação
{TDll}
construtorTDll.Create;
começar
Proprietário:=nulo;
NomedoArquivo:=´´;
FMódulo:=0;
FPermitir:=Verdadeiro;
fim;
destruidorTDll.Destroy;
var
Gerente:TDllManager;
começar
Carregado:=Falso;
ifFOwner<>nilthen
começar
//在拥有者中删除自身
Gerente:=Proprietário;
//未防止在TDllManager中重复删除,因此需要将
//FOwner设置为nil;<--此段代码和TDllManager.Notify需要配合
//才能确保正确。
Proprietário:=nulo;
Gerente.Remove(Auto);
fim;
herdado;
fim;
functionTDll.GetLoaded:Boolean;
começar
resultado:=FMódulo<>0;
fim;
functionTDll.GetProcAddress(constOrder:Longint):FARPROC;
começar
ifLoadedentão
resultado:=Windows.GetProcAddress(FModule,Pointer(Order))
outro
raiseEDllError.CreateFmt(´DoLoadbeforeGetProcAddressof%u´,[DWORD(Order)]);
fim;
functionTDll.GetProcAddress(constProcName:String):FARPROC;
começar
ifLoadedentão
resultado:=Windows.GetProcAddress(FModule,PChar(ProcName))
outro
raiseEDllError.CreateFmt(´DoLoadbeforeGetProcAddressof%s´,[ProcName]);
fim;
procedimentoTDll.SetLoaded(constValue:Boolean);
começar
ifLoaded<>Valuethen
começar
ifnotValuethen
começar
Afirmar(FModule<>0);
DoBeforeDllUnLoaded;
tentar
Biblioteca Livre(FModule);
FMódulo:=0;
exceto
Application.HandleException(Self);
fim;
DoDllUnLoaded;
fim
outro
começar
FModule:=LoadLibrary(PChar(FFileName));
tentar
Win32Check(FModule<>0);
DoDllLoaded;
exceto
OnE:Exceçãodo
começar
ifFModule<>0então
começar
Biblioteca Livre(FModule);
FMódulo:=0;
fim;
raiseEDllError.CreateFmt(´LoadLibraryError:%s´,[E.Message]);
fim;
fim;
fim;
fim;
fim;
procedimentoTDll.SetFileName(constValue:String);
começar
ifLoadedentão
raiseEDllError.CreateFmt(´DoUnloadbeforeloadanotherModulnomeado:%s´,
[Valor]);
ifFFileName<>Valuethen
começar
FFileName:=Valor;
DoFileNameChange;
fim;
fim;
procedimentoTDll.DoFileNameChange;
começar
//não faça nada.
fim;
procedimentoTDll.DoDllLoaded;
começar
ifAssigned(FOwner)eAssigned(FOwner.OnDllLoaded)então
FOwner.OnDllLoaded(FOwner,Self);
fim;
procedimentoTDll.DoDllUnLoaded;
começar
//não faça nada.
fim;
procedimentoTDll.DoPermitChange;
começar
//não faça nada.
fim;
procedimentoTDll.SetPermit(constValue:Boolean);
começar
ifFPermit<>Valuethen
começar
FPermit:=Valor;
DoPermitChange;
fim;
fim;
procedimentoTDll.DoBeforeDllUnLoaded;
começar
ifAssigned(FOwner)eAssigned(FOwner.OnDllBeforeUnLoaded)então
FOwner.OnDllBeforeUnLoaded(FOwner,Self);
fim;
{TDllManager}
functionTDllManager.Add(constFileName:String):Integer;
var
Dll:TDll;
começar
resultado:=-1;
Trancar;
tentar
ifDllsByName[NomedoArquivo]=nilthen
começar
Dll:=FDllClass.Create;
Dll.NomeArquivo:=NomeArquivo;
resultado:=Adicionar(Dll);
fim
outro
resultado:=-1;
finalmente
Desbloquear;
fim;
fim;
construtorTDllManager.Create;
começar
FDllClass:=TDll;
InitializeCriticalSection(FLock);
fim;
destruidorTDllManager.Destroy;
começar
DeleteCriticalSection(FLock);
herdado;
fim;
functionTDllManager.GetDlls(constIndex:Integer):TDll;
começar
Trancar;
tentar
if(Índice>=0)e(Índice<=Contagem-1)então
resultado:=Itens[Índice]
outro
raiseEDllError.CreateFmt(´ErrorIndexofGetDlls,Value:%d,TotalCount:%d´,[Index,Count]);
finalmente
Desbloquear;
fim;
fim;
functionTDllManager.GetDllsByName(constFileName:String):TDll;
var
Eu:Inteiro;
começar
Trancar;
tentar
I:=IndexOf(NomeArquivo);
se eu>=0então
resultado:=DLLs[I]
outro
resultado:=nulo;
finalmente
Desbloquear;
fim;
fim;
functionTDllManager.IndexOf(constFileName:String):Integer;
var
Eu:Inteiro;
começar
resultado:=-1;
Trancar;
tentar
forI:=0toCount-1do
ifCompareText(FileName,Dlls[I].FileName)=0então
começar
resultado:=eu;
quebrar;
fim;
finalmente
Desbloquear;
fim;
fim;
procedimentoTDllManager.Lock;
começar
OutputDebugString(Pchar(´TRLockDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));
EnterCriticalSection(FLock);
OutputDebugString(Pchar(´LockedDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));
fim;
procedimentoTDllManager.Notify(Ptr:Ponteiro;Ação:TListNotification);
começar
ifAction=lnDeletedthen
começar
//若TDll(Ptr).Owner和Self不同,则
//表明由TDll.Destroy触发;
ifTDll(Ptr).Owner=Selfentão
começar
//防止FOproprietário设置为nil之后相关事件不能触发
TDll(Ptr).DoBeforeDllUnLoaded;
TDll(Ptr).FOproprietário:=nil;
TDll(Ptr).Livre;
fim;
fim
outro
ifAction=lnAdicionadoentão
TDll(Ptr).FOwner:=Próprio;
herdado;
fim;
functionTDllManager.Remove(constFileName:String):Integer;
var
Eu:Inteiro;
começar
resultado:=-1;
Trancar;
tentar
I:=IndexOf(NomeArquivo);
se eu>=0então
resultado:=Remover(DLLs[I])
outro
resultado:=-1;
finalmente
Desbloquear;
fim;
fim;
procedimentoTDllManager.UnLock;
começar
LeaveCriticalSection(FLock);
OutputDebugString(Pchar(´UnLockDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));
fim;
fim.