unituntDllManager;
인터페이스
용도
Windows, 클래스, SysUtils, 양식;
유형
EDllError=클래스(예외);
TDllClass=TDll 클래스;
TDll=클래스;
TDllEvent=procedure(Sender: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;overload;
functionRemove(constFileName:String):Integer;overload;
절차잠금;
절차잠금 해제;
propertyDllClass:TDllClassreadFDllClasswriteFDllClass;
propertyDlls[constIndex:Integer]:TDllreadGetDlls;default;
propertyDllsByName[constFileName:String]:TDllreadGetDllsByName;
propertyOnDllLoaded:TDllEventreadFOnDllLoadwriteFOnDllLoad;
propertyOnDllBeforeUnLoaded:TDllEventreadFOnDllBeforeUnLoadedwriteFOnDllBeforeUnLoaded;
끝;
{TDll
o代表一个Dll,Windows.HModule
o销毁时自动재Owner中删除自身;
o子类可通过覆盖overrideDoDllLoaded,以及DoDllUnLoaded进行功能扩 Exhibition;
}
TDll=클래스(TObject)
사적인
FOwner:TDllManager;
F모듈:HMODULE;
F파일 이름:문자열;
FPermit:부울;
절차SetFileName(constValue:String);
functionGetLoaded:부울;
절차SetLoaded(constValue:Boolean);
절차SetPermit(constValue:Boolean);
보호됨
절차DoDllLoaded;가상;
절차DoBeforeDllUnLoaded;가상;
절차DoDllUnLoaded;가상;
절차DoFileNameChange;가상;
절차DoPermitChange;가상;
공공의
생성자생성;가상;
소멸자파괴;재정의;
functionGetProcAddress(constOrder:Longint):FARPROC;오버로드;
functionGetProcAddress(constProcName:String):FARPROC;오버로드;
propertyFileName:StringreadFFileNamewriteSetFileName;
propertyLoaded:BooleanreadGetLoadedwriteSetLoaded;
propertyOwner:TDllManagerreadFOwner;
propertyPermit:BooleanreadFPermitwriteSetPermit;
끝;
구현
{TDll}
생성자TDll.Create;
시작하다
FOwner:=nil;
F파일이름:='';
F모듈:=0;
FPermit:=참;
끝;
소멸자TDll.Destroy;
var
관리자:TDllManager;
시작하다
로드됨:=거짓;
ifFOwner<>nilthen
시작하다
//현재 拥有者中删除自身
관리자:=F소유자;
//未防止在TDllManager中重复删除,因此需要将
//FOwner设置为nil;<--此段代码和TDllManager.Notify需要配합
//才能确保正确。
FOwner:=nil;
Manager.Remove(Self);
끝;
상속됨;
끝;
functionTDll.GetLoaded:Boolean;
시작하다
결과:=FModule<>0;
끝;
functionTDll.GetProcAddress(constOrder:Longint):FARPROC;
시작하다
ifLoaded다음
결과:=Windows.GetProcAddress(FModule,Pointer(Order))
또 다른
raiseEDllError.CreateFmt('DoLoadbeforeGetProcAddressof%u',[DWORD(Order)]);
끝;
functionTDll.GetProcAddress(constProcName:String):FARPROC;
시작하다
ifLoaded다음
결과:=Windows.GetProcAddress(FModule,PChar(ProcName))
또 다른
raiseEDllError.CreateFmt('DoLoadbeforeGetProcAddressof%s',[ProcName]);
끝;
절차TDll.SetLoaded(constValue:Boolean);
시작하다
ifLoaded<>값then
시작하다
ifnotValuethen
시작하다
Assert(FModule<>0);
DoBeforeDllUnLoaded;
노력하다
FreeLibrary(FM모듈);
F모듈:=0;
제외하고
Application.HandleException(Self);
끝;
DoDllUnLoaded;
끝
또 다른
시작하다
FModule:=LoadLibrary(PChar(FFileName));
노력하다
Win32Check(FModule<>0);
DoDllLoaded;
제외하고
OnE:예외do
시작하다
ifFModule<>0then
시작하다
FreeLibrary(FM모듈);
F모듈:=0;
끝;
raiseEDllError.CreateFmt('LoadLibraryError:%s',[E.Message]);
끝;
끝;
끝;
끝;
끝;
절차TDll.SetFileName(constValue:String);
시작하다
ifLoaded다음
raiseEDllError.CreateFmt('다른 모듈 이름:%s'을 로드하기 전에 Unload 실행,
[값]);
ifFFileName<>값then
시작하다
FFileName:=값;
DoFileNameChange;
끝;
끝;
절차TDll.DoFileNameChange;
시작하다
//아무것도 하지 마세요.
끝;
절차TDll.DoDllLoaded;
시작하다
ifAssigned(FOwner)및Assigned(FOwner.OnDllLoaded)then
FOwner.OnDllLoaded(FOwner,Self);
끝;
절차TDll.DoDllUnLoaded;
시작하다
//아무것도 하지 마세요.
끝;
절차TDll.DoPermitChange;
시작하다
//아무것도 하지 마세요.
끝;
절차TDll.SetPermit(constValue:Boolean);
시작하다
ifFPermit<>값then
시작하다
FPermit:=값;
DoPermitChange;
끝;
끝;
절차TDll.DoBeforeDllUnLoaded;
시작하다
ifAssigned(FOwner)및Assigned(FOwner.OnDllBeforeUnLoaded)then
FOwner.OnDllBeforeUnLoaded(FOwner,Self);
끝;
{TDllManager}
functionTDllManager.Add(constFileName:String):Integer;
var
DLL:TDll;
시작하다
결과:=-1;
잠그다;
노력하다
ifDllsByName[파일 이름]=nilthen
시작하다
Dll:=FDllClass.Create;
Dll.파일이름:=파일이름;
결과:=추가(Dll);
끝
또 다른
결과:=-1;
마지막으로
터놓다;
끝;
끝;
생성자TDllManager.Create;
시작하다
FDllClass:=TDll;
초기화CriticalSection(FLock);
끝;
소멸자TDllManager.Destroy;
시작하다
DeleteCriticalSection(FLock);
상속됨;
끝;
functionTDllManager.GetDlls(constIndex:Integer):TDll;
시작하다
잠그다;
노력하다
if(색인>=0)and(색인<=Count-1)then
결과:=항목[색인]
또 다른
raiseEDllError.CreateFmt('ErrorIndexofGetDlls,값:%d,TotalCount:%d',[Index,Count]);
마지막으로
터놓다;
끝;
끝;
functionTDllManager.GetDllsByName(constFileName:String):TDll;
var
I:정수;
시작하다
잠그다;
노력하다
I:=IndexOf(파일이름);
I>=0이면
결과:=Dlls[I]
또 다른
결과:=nil;
마지막으로
터놓다;
끝;
끝;
functionTDllManager.IndexOf(constFileName:String):Integer;
var
I:정수;
시작하다
결과:=-1;
잠그다;
노력하다
forI:=0toCount-1do
ifCompareText(FileName,Dlls[I].FileName)=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=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;
var
I:정수;
시작하다
결과:=-1;
잠그다;
노력하다
I:=IndexOf(파일이름);
I>=0이면
결과:=제거(Dlls[I])
또 다른
결과:=-1;
마지막으로
터놓다;
끝;
끝;
절차TDllManager.UnLock;
시작하다
LeaveCriticalSection(FLock);
OutputDebugString(Pchar('UnLockDM'+IntToStr(GetCurrentThreadId)+':'+IntToStr(DWORD(Self))));
끝;
끝.