ユニットDllマネージャー;
インタフェース
用途
Windows、クラス、SysUtils、フォーム;
タイプ
EDllError=クラス(例外);
TDllClass=TDll のクラス;
TDll=クラス;
TDllEvent=プロシージャ(Sender:TObject;ADll:TDll)ofObject;
{TDllマネージャー
o Dll の管理機能を提供します。
o追加時自動创建TDllオブジェクト,ただし谝试装填;
o削除時自動销毁TDll对オブジェクト;
}
TDllManager=クラス(TList)
プライベート
FLock:TRTLCriticalSection;
FDllクラス:TDllクラス;
FOnDllLoad:TDllEvent;
FOnDllBeforeUnLoaded:TDllEvent;
functionGetDlls(constIndex:Integer):TDll;
functionGetDllsByName(constFileName:String):TDll;
保護された
プロシージャ通知(Ptr:ポインタ;アクション:TListNotification);オーバーライド;
公共
コンストラクター作成;
デストラクタDestroy;オーバーライド;
functionAdd(constFileName:String):Integer;オーバーロード;
functionIndexOf(constFileName:String):整数;オーバーロード;
functionRemove(constFileName:String):Integer;オーバーロード;
プロシージャロック;
プロシージャロック解除;
propertyDllClass:TDllClassreadFDllClasswriteFDllClass;
propertyDlls[constIndex:Integer]:TDllreadGetDlls;デフォルト;
propertyDllsByName[constFileName:String]:TDllreadGetDllsByName;
propertyOnDllLoaded:TDllEventreadFOnDllLoadwriteFOnDllLoad;
propertyOnDllBeforeUnLoaded:TDllEventreadFOnDllBeforeUnLoadedwriteFOnDllBeforeUnLoaded;
終わり;
{TDll
o代表的なDll、Windows.HModule
o销毁時自動的に所有者内で自身を削除します。
o子クラスは、DoDllLoaded および DoDllUnLoaded をオーバーライドすることによって機能拡張を実行できます。
}
TDll=クラス(Tオブジェクト)
プライベート
F所有者:TDllマネージャー;
Fモジュール:Hモジュール;
Fファイル名:文字列;
FPermit:ブール値;
プロシージャセットファイル名(constValue:String);
functionGetLoaded:ブール値;
プロシージャセットロード(constValue:Boolean);
プロシージャSetPermit(constValue:Boolean);
保護された
プロシージャDoDllLoaded;仮想;
プロシージャDoBeforeDllUnLoaded;仮想;
プロシージャDoDllUnLoaded;仮想;
プロシージャDoFileNameChange;仮想;
プロシージャDoPermitChange;仮想;
公共
コンストラクター作成;仮想;
デストラクタDestroy;オーバーライド;
functionGetProcAddress(constOrder:Longint):FARPROC;オーバーロード;
functionGetProcAddress(constProcName:String):FARPROC;オーバーロード;
propertyFileName:StringreadFFileNamewriteSetFileName;
propertyLoaded:BooleanreadGetLoadedwriteSetLoaded;
propertyOwner:TDllManagerreadFOwner;
propertyPermit:BooleanreadFPermitwriteSetPermit;
終わり;
実装
{TDll}
コンストラクターTDll.Create;
始める
F所有者:=nil;
Fファイル名:=´´;
Fモジュール:=0;
FPermit:=True;
終わり;
デストラクタTDll.Destroy;
変数
マネージャー:TDllマネージャー;
始める
ロード済み:=False;
ifFOwner<>nilthen
始める
//在拥所有者中删除自身
マネージャー:=F 所有者;
//TDllManager での重複削除は防止されていないため、必要があります
//FOwner 設定は nil;<--この段代コードと TDllManager.Notify は連携が必要です
// 才能は正しく保たれます。
F所有者:=nil;
Manager.Remove(Self);
終わり;
継承された。
終わり;
functionTDll.GetLoaded:ブール値;
始める
結果:=FModule<>0;
終わり;
functionTDll.GetProcAddress(constOrder:Longint):FARPROC;
始める
ロード済みの場合その後
result:=Windows.GetProcAddress(FModule,Pointer(Order))
それ以外
raiseEDllError.CreateFmt('DoLoadbeforeGetProcAddressof%u',[DWORD(Order)]);
終わり;
functionTDll.GetProcAddress(constProcName:String):FARPROC;
始める
ロード済みの場合その後
result:=Windows.GetProcAddress(FModule,PChar(ProcName))
それ以外
raiseEDllError.CreateFmt('DoLoadbeforeGetProcAddressof%s',[ProcName]);
終わり;
プロシージャTDll.SetLoaded(constValue:Boolean);
始める
ifLoaded<>値then
始める
ifnot値then
始める
Assert(FModule<>0);
DoBeforeDllUnLoaded;
試す
フリーライブラリ(FModule);
Fモジュール:=0;
を除外する
Application.HandleException(Self);
終わり;
DoDllUnLoaded;
終わり
それ以外
始める
FModule:=LoadLibrary(PChar(FFileName));
試す
Win32Check(FModule<>0);
DoDllロード済み;
を除外する
OneE:例外
始める
ifFModule<>0then
始める
フリーライブラリ(FModule);
Fモジュール:=0;
終わり;
raiseEDllError.CreateFmt('LoadLibraryError:%s',[E.Message]);
終わり;
終わり;
終わり;
終わり;
終わり;
プロシージャTDll.SetFileName(constValue:String);
始める
ロード済みの場合その後
raiseEDllError.CreateFmt('別のモジュール名:%s をロードする前にアンロードを実行',
[価値]);
ifFファイル名<>値then
始める
Fファイル名:=値;
DoFileNameChange;
終わり;
終わり;
プロシージャTDll.DoFileNameChange;
始める
//何もしない。
終わり;
プロシージャTDll.DoDllLoaded;
始める
ifAssigned(FOwner) and Assigned(FOwner.OnDllLoaded) then
FOwner.OnDllLoaded(FOwner,Self);
終わり;
プロシージャTDll.DoDllUnLoaded;
始める
//何もしない。
終わり;
プロシージャTDll.DoPermitChange;
始める
//何もしない。
終わり;
プロシージャTDll.SetPermit(constValue:Boolean);
始める
ifFPermit<>Valuethen
始める
F許可:=値;
DoPermitChange;
終わり;
終わり;
プロシージャTDll.DoBeforeDllUnLoaded;
始める
ifAssigned(FOwner) and Assigned(FOwner.OnDllBeforeUnLoaded) then
FOwner.OnDllBeforeUnLoaded(FOwner,Self);
終わり;
{TDllマネージャー}
functionTDllManager.Add(constFileName:String):Integer;
変数
DLL:TDll;
始める
結果:=-1;
ロック;
試す
ifDllsByName[ファイル名]=nilthen
始める
DLL:=FDllClass.Create;
Dll.FileName:=ファイル名;
結果:=追加(Dll);
終わり
それ以外
結果:=-1;
ついに
ロックを解除します。
終わり;
終わり;
コンストラクターTDllManager.Create;
始める
FDllクラス:=TDll;
InitializeCriticalSection(FLock);
終わり;
デストラクターTDllManager.Destroy;
始める
クリティカルセクションを削除(FLock);
継承された。
終わり;
functionTDllManager.GetDlls(constIndex:Integer):TDll;
始める
ロック;
試す
if(インデックス>=0)and(インデックス<=カウント-1)then
result:=アイテム[インデックス]
それ以外
raiseEDllError.CreateFmt('ErrorIndexofGetDlls,Value:%d,TotalCount:%d',[Index,Count]);
ついに
ロックを解除します。
終わり;
終わり;
functionTDllManager.GetDllsByName(constFileName:String):TDll;
変数
I:整数;
始める
ロック;
試す
I:=インデックスOf(ファイル名);
ifI>=0then
結果:=Dlls[I]
それ以外
結果:=nil;
ついに
ロックを解除します。
終わり;
終わり;
functionTDllManager.IndexOf(constFileName:String):Integer;
変数
I:整数;
始める
結果:=-1;
ロック;
試す
forI:=0toCount-1do
ifCompareText(ファイル名,Dlls[I].ファイル名)=0then
始める
結果:=I;
壊す;
終わり;
ついに
ロックを解除します。
終わり;
終わり;
プロシージャTDllManager.Lock;
始める
OutputDebugString(Pchar('TRLockDM'+IntToStr(GetCurrentThreadId)+':'+IntToStr(DWORD(Self))));
EnterCriticalSection(FLock);
OutputDebugString(Pchar('LockedDM'+IntToStr(GetCurrentThreadId)+':'+IntToStr(DWORD(Self))));
終わり;
プロシージャTDllManager.Notify(Ptr:Pointer;Action:TListNotification);
始める
ifAction=ln削除してから
始める
//若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:=インデックスOf(ファイル名);
ifI>=0then
結果:=削除(Dlls[I])
それ以外
結果:=-1;
ついに
ロックを解除します。
終わり;
終わり;
プロシージャTDllManager.UnLock;
始める
LeaveCriticalSection(FLock);
OutputDebugString(Pchar('UnLockDM'+IntToStr(GetCurrentThreadId)+':'+IntToStr(DWORD(Self))));
終わり;
終わり。