單元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))));
結尾;
結尾。