单元untDllManager;
界面
用途
窗口、类、SysUtils、表单;
类型
EDllError=类(异常);
TDllClass=TDll 类;
TDll=类;
TDllEvent=过程(发送者:TObject;ADll:TDll)ofObject;
{TDLL管理器
o 提供对Dll的管理功能;
oAdd时自动创建TDll对象,但不尝试加载;
oDelete时自动引用TDll对象;
}
TDllManager=类(TList)
私人的
FLock:TRTLCriticalSection;
FDllClass:TDllClass;
FOnDllLoad:TDllEvent;
FOnDllBeforeUnLoaded:TDllEvent;
functionGetDlls(constIndex:Integer):TDll;
functionGetDllsByName(constFileName:String):TDll;
受保护的
procedureNotify(Ptr:Pointer;Action:TListNotification);覆盖;
民众
构造函数创建;
析构函数销毁;覆盖;
functionAdd(constFileName:String):Integer;重载;
functionIndexOf(constFileName:String):Integer;重载;
functionRemove(constFileName:String):Integer;重载;
过程锁;
程序解锁;
propertyDllClass:TDllClassreadFDllClasswriteFDllClass;
propertyDlls[constIndex:Integer]:TDllreadGetDlls;默认;
propertyDllsByName[constFileName:String]:TDllreadGetDllsByName;
propertyOnDllLoaded:TDllEventreadFOnDllLoadwriteFOnDllLoad;
propertyOnDllBeforeUnLoaded:TDllEventreadFOnDllBeforeUnLoadedwriteFOnDllBeforeUnLoaded;
结尾;
{TDll
o代表一个Dll,Windows.HModule
o 情报时自动在Owner中删除自身;
o子类可以通过覆盖overrideDoDllLoaded,以及DoDllUnLoaded进行功能扩展;
}
TDll=类(TObject)
私人的
所有者:TDllManager;
F模块:HMODULE;
F文件名:字符串;
FPermit:布尔值;
procedureSetFileName(constValue:String);
函数GetLoaded:布尔值;
procedureSetLoaded(constValue:Boolean);
procedureSetPermit(constValue:Boolean);
受保护的
procedureDoDllLoaded;虚拟;
procedureDoBeforeDllUnLoaded;虚拟;
procedureDoDllUnLoaded;虚拟;
procedureDoFileNameChange;虚拟;
procedureDoPermitChange;虚拟;
民众
构造函数创建;虚拟;
析构函数销毁;覆盖;
functionGetProcAddress(constOrder:Longint):FARPROC;重载;
functionGetProcAddress(constProcName:String):FARPROC;重载;
属性文件名:StringreadFFileNamewriteSetFileName;
属性Loaded:BooleanreadGetLoadedwriteSetLoaded;
propertyOwner:TDllManagerreadFOwner;
propertyPermit:BooleanreadFPermitwriteSetPermit;
结尾;
执行
{TDll}
构造函数TDll.Create;
开始
FOwner:=nil;
F文件名:=´´;
F模块:=0;
FPermit:=真;
结尾;
析构函数TDll.Destroy;
变量
管理员:TDllManager;
开始
已加载:=假;
ifFOwner<>niilthen
开始
//在拥有者中删除自身
经理:=业主;
//未防止在TDllManager中重复删除,因此需要将
//FOwner设置为nil;<--此段代码和TDllManager.Notify需要配合
//才能确保正确。
FOwner:=nil;
经理.删除(自我);
结尾;
遗传;
结尾;
functionTDll.GetLoaded:布尔值;
开始
结果:=FModule<>0;
结尾;
functionTDll.GetProcAddress(constOrder:Longint):FARPROC;
开始
如果加载则
结果:=Windows.GetProcAddress(FModule,指针(顺序))
别的
raiseEDllError.CreateFmt('DoLoadbeforeGetProcAddressof%u',[DWORD(Order)]);
结尾;
functionTDll.GetProcAddress(constProcName:String):FARPROC;
开始
如果加载则
结果:=Windows.GetProcAddress(FModule,PChar(ProcName))
别的
raiseEDllError.CreateFmt('DoLoadbeforeGetProcAddressof%s',[ProcName]);
结尾;
procedureTDll.SetLoaded(constValue:Boolean);
开始
ifLoaded<>Valuethen
开始
如果不值则
开始
断言(FModule<>0);
DoBeforeDllUnLoaded;
尝试
自由库(FModule);
F模块:=0;
除了
Application.HandleException(Self);
结尾;
DoDllUnLoaded;
结尾
别的
开始
FModule:=LoadLibrary(PChar(FFileName));
尝试
Win32Check(FModule<>0);
DoDll加载;
除了
一个E:例外
开始
ifFModule<>0then
开始
自由库(FModule);
F模块:=0;
结尾;
raiseEDllError.CreateFmt('LoadLibraryError:%s',[E.Message]);
结尾;
结尾;
结尾;
结尾;
结尾;
procedureTDll.SetFileName(constValue:String);
开始
如果加载则
raiseEDllError.CreateFmt('DoUnloadbeforeloadanotherModulenamed:%s',
[价值]);
ifFFileName<>Valuethen
开始
F文件名:=值;
文件名更改;
结尾;
结尾;
procedureTDll.DoFileNameChange;
开始
//什么也不做。
结尾;
procedureTDll.DoDllLoaded;
开始
ifAssigned(FOwner)andAssigned(FOwner.OnDllLoaded)then
FOwner.OnDllLoaded(FOwner,Self);
结尾;
procedureTDll.DoDllUnLoaded;
开始
//什么也不做。
结尾;
procedureTDll.DoPermitChange;
开始
//什么也不做。
结尾;
procedureTDll.SetPermit(constValue:Boolean);
开始
ifFPermit<>Valuethen
开始
FPermit:=值;
允许更改;
结尾;
结尾;
procedureTDll.DoBeforeDllUnLoaded;
开始
ifAssigned(FOwner)andAssigned(FOwner.OnDllBeforeUnLoaded)then
FOwner.OnDllBeforeUnLoaded(FOwner,Self);
结尾;
{TDllManager}
functionTDllManager.Add(constFileName:String):Integer;
变量
DLL:TDLL;
开始
结果:=-1;
锁;
尝试
ifDllsByName[文件名]=nilthen
开始
Dll:=FDllClass.Create;
Dll.文件名:=文件名;
结果:=添加(Dll);
结尾
别的
结果:=-1;
最后
开锁;
结尾;
结尾;
构造函数TDllManager.Create;
开始
FDllClass:=TDll;
初始化CriticalSection(FLock);
结尾;
析构函数TDllManager.Destroy;
开始
删除关键部分(FLock);
遗传;
结尾;
functionTDllManager.GetDlls(constIndex:Integer):TDll;
开始
锁;
尝试
if(Index>=0)and(Index<=Count-1)then
结果:=项目[索引]
别的
raiseEDllError.CreateFmt('ErrorIndexofGetDlls,值:%d,TotalCount:%d',[索引,计数]);
最后
开锁;
结尾;
结尾;
functionTDllManager.GetDllsByName(constFileName:String):TDll;
变量
I:整数;
开始
锁;
尝试
I:=IndexOf(文件名);
如果我>=0那么
结果:=Dlls[I]
别的
结果:=零;
最后
开锁;
结尾;
结尾;
functionTDllManager.IndexOf(constFileName:String):Integer;
变量
I:整数;
开始
结果:=-1;
锁;
尝试
forI:=0toCount-1do
ifCompareText(文件名,Dlls[I].文件名)=0then
开始
结果:=我;
休息;
结尾;
最后
开锁;
结尾;
结尾;
procedureTDllManager.Lock;
开始
OutputDebugString(Pchar('TRLockDM'+IntToStr(GetCurrentThreadId)+':'+IntToStr(DWORD(Self))));
EnterCriticalSection(FLock);
OutputDebugString(Pchar('LockedDM'+IntToStr(GetCurrentThreadId)+':'+IntToStr(DWORD(Self))));
结尾;
procedureTDllManager.Notify(Ptr:Pointer;Action:TListNotification);
开始
ifAction=lnDeletedthen
开始
//若TDll(Ptr).Owner和Self不同,则
//表明由TDll.Destroy触发;
ifTDll(Ptr).Owner=Selfthen
开始
//防止FOwner设置为nil之后相关事件无法触发
TDll(Ptr).DoBeforeDllUnLoaded;
TDll(Ptr).FOwner:=nil;
TDll(Ptr).免费;
结尾;
结尾
别的
ifAction=lnAddedthen
TDll(Ptr).FOwner:=自己;
遗传;
结尾;
functionTDllManager.Remove(constFileName:String):Integer;
变量
I:整数;
开始
结果:=-1;
锁;
尝试
I:=IndexOf(文件名);
如果我>=0那么
结果:=删除(Dlls[I])
别的
结果:=-1;
最后
开锁;
结尾;
结尾;
procedureTDllManager.UnLock;
开始
离开关键部分(FLock);
OutputDebugString(Pchar('UnLockDM'+IntToStr(GetCurrentThreadId)+':'+IntToStr(DWORD(Self))));
结尾;
结尾。