插件管理框架 for Delphi(二)_Delphi教程-查字典教程网
插件管理框架 for Delphi(二)
插件管理框架 for Delphi(二)
发布时间:2016-12-28 来源:查字典编辑
摘要:unituntDllManager;interfaceusesWindows,Classes,SysUtils,Forms;typeEDll...

unituntDllManager;

interface

uses

Windows,Classes,SysUtils,Forms;

type

EDllError=Class(Exception);

TDllClass=ClassofTDll;

TDll=Class;

TDllEvent=procedure(Sender:TObject;ADll:TDll)ofObject;

{TDllManager

o提供对Dll的管理功能;

oAdd时自动创建TDll对象,但不尝试装载;

oDelete时自动销毁TDll对象;

}

TDllManager=Class(TList)

private

FLock:TRTLCriticalSection;

FDllClass:TDllClass;

FOnDllLoad:TDllEvent;

FOnDllBeforeUnLoaded:TDllEvent;

functionGetDlls(constIndex:Integer):TDll;

functionGetDllsByName(constFileName:String):TDll;

protected

procedureNotify(Ptr:Pointer;Action:TListNotification);override;

public

constructorCreate;

destructorDestroy;override;

functionAdd(constFileName:String):Integer;overload;

functionIndexOf(constFileName:String):Integer;overload;

functionRemove(constFileName:String):Integer;overload;

procedureLock;

procedureUnLock;

propertyDllClass:TDllClassreadFDllClasswriteFDllClass;

propertyDlls[constIndex:Integer]:TDllreadGetDlls;default;

propertyDllsByName[constFileName:String]:TDllreadGetDllsByName;

propertyOnDllLoaded:TDllEventreadFOnDllLoadwriteFOnDllLoad;

propertyOnDllBeforeUnLoaded:TDllEventreadFOnDllBeforeUnLoadedwriteFOnDllBeforeUnLoaded;

end;

{TDll

o代表一个Dll,Windows.HModule

o销毁时自动在Owner中删除自身;

o子类可通过覆盖overrideDoDllLoaded,以及DoDllUnLoaded进行功能扩展;

}

TDll=Class(TObject)

private

FOwner:TDllManager;

FModule:HMODULE;

FFileName:String;

FPermit:Boolean;

procedureSetFileName(constValue:String);

functionGetLoaded:Boolean;

procedureSetLoaded(constValue:Boolean);

procedureSetPermit(constValue:Boolean);

protected

procedureDoDllLoaded;virtual;

procedureDoBeforeDllUnLoaded;virtual;

procedureDoDllUnLoaded;virtual;

procedureDoFileNameChange;virtual;

procedureDoPermitChange;virtual;

public

constructorCreate;virtual;

destructorDestroy;override;

functionGetProcAddress(constOrder:Longint):FARPROC;overload;

functionGetProcAddress(constProcName:String):FARPROC;overload;

propertyFileName:StringreadFFileNamewriteSetFileName;

propertyLoaded:BooleanreadGetLoadedwriteSetLoaded;

propertyOwner:TDllManagerreadFOwner;

propertyPermit:BooleanreadFPermitwriteSetPermit;

end;

implementation

{TDll}

constructorTDll.Create;

begin

FOwner:=nil;

FFileName:=´´;

FModule:=0;

FPermit:=True;

end;

destructorTDll.Destroy;

var

Manager:TDllManager;

begin

Loaded:=False;

ifFOwner<>nilthen

begin

//在拥有者中删除自身

Manager:=FOwner;

//未防止在TDllManager中重复删除,因此需要将

//FOwner设置为nil;<--此段代码和TDllManager.Notify需要配合

//才能确保正确。

FOwner:=nil;

Manager.Remove(Self);

end;

inherited;

end;

functionTDll.GetLoaded:Boolean;

begin

result:=FModule<>0;

end;

functionTDll.GetProcAddress(constOrder:Longint):FARPROC;

begin

ifLoadedthen

result:=Windows.GetProcAddress(FModule,Pointer(Order))

else

raiseEDllError.CreateFmt(´DoLoadbeforeGetProcAddressof"%u"´,[DWORD(Order)]);

end;

functionTDll.GetProcAddress(constProcName:String):FARPROC;

begin

ifLoadedthen

result:=Windows.GetProcAddress(FModule,PChar(ProcName))

else

raiseEDllError.CreateFmt(´DoLoadbeforeGetProcAddressof"%s"´,[ProcName]);

end;

procedureTDll.SetLoaded(constValue:Boolean);

begin

ifLoaded<>Valuethen

begin

ifnotValuethen

begin

Assert(FModule<>0);

DoBeforeDllUnLoaded;

try

FreeLibrary(FModule);

FModule:=0;

except

Application.HandleException(Self);

end;

DoDllUnLoaded;

end

else

begin

FModule:=LoadLibrary(PChar(FFileName));

try

Win32Check(FModule<>0);

DoDllLoaded;

except

OnE:Exceptiondo

begin

ifFModule<>0then

begin

FreeLibrary(FModule);

FModule:=0;

end;

raiseEDllError.CreateFmt(´LoadLibraryError:%s´,[E.Message]);

end;

end;

end;

end;

end;

procedureTDll.SetFileName(constValue:String);

begin

ifLoadedthen

raiseEDllError.CreateFmt(´DoUnloadbeforeloadanotherModulenamed:"%s"´,

[Value]);

ifFFileName<>Valuethen

begin

FFileName:=Value;

DoFileNameChange;

end;

end;

procedureTDll.DoFileNameChange;

begin

//dononthing.

end;

procedureTDll.DoDllLoaded;

begin

ifAssigned(FOwner)andAssigned(FOwner.OnDllLoaded)then

FOwner.OnDllLoaded(FOwner,Self);

end;

procedureTDll.DoDllUnLoaded;

begin

//dononthing.

end;

procedureTDll.DoPermitChange;

begin

//dononthing.

end;

procedureTDll.SetPermit(constValue:Boolean);

begin

ifFPermit<>Valuethen

begin

FPermit:=Value;

DoPermitChange;

end;

end;

procedureTDll.DoBeforeDllUnLoaded;

begin

ifAssigned(FOwner)andAssigned(FOwner.OnDllBeforeUnLoaded)then

FOwner.OnDllBeforeUnLoaded(FOwner,Self);

end;

{TDllManager}

functionTDllManager.Add(constFileName:String):Integer;

var

Dll:TDll;

begin

result:=-1;

Lock;

try

ifDllsByName[FileName]=nilthen

begin

Dll:=FDllClass.Create;

Dll.FileName:=FileName;

result:=Add(Dll);

end

else

result:=-1;

finally

UnLock;

end;

end;

constructorTDllManager.Create;

begin

FDllClass:=TDll;

InitializeCriticalSection(FLock);

end;

destructorTDllManager.Destroy;

begin

DeleteCriticalSection(FLock);

inherited;

end;

functionTDllManager.GetDlls(constIndex:Integer):TDll;

begin

Lock;

try

if(Index>=0)and(Index<=Count-1)then

result:=Items[Index]

else

raiseEDllError.CreateFmt(´ErrorIndexofGetDlls,Value:%d,TotalCount:%d´,[Index,Count]);

finally

UnLock;

end;

end;

functionTDllManager.GetDllsByName(constFileName:String):TDll;

var

I:Integer;

begin

Lock;

try

I:=IndexOf(FileName);

ifI>=0then

result:=Dlls[I]

else

result:=nil;

finally

UnLock;

end;

end;

functionTDllManager.IndexOf(constFileName:String):Integer;

var

I:Integer;

begin

result:=-1;

Lock;

try

forI:=0toCount-1do

ifCompareText(FileName,Dlls[I].FileName)=0then

begin

result:=I;

break;

end;

finally

UnLock;

end;

end;

procedureTDllManager.Lock;

begin

OutputDebugString(Pchar(´TRLockDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));

EnterCriticalSection(FLock);

OutputDebugString(Pchar(´LockedDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));

end;

procedureTDllManager.Notify(Ptr:Pointer;Action:TListNotification);

begin

ifAction=lnDeletedthen

begin

//若TDll(Ptr).Owner和Self不同,则

//表明由TDll.Destroy触发;

ifTDll(Ptr).Owner=Selfthen

begin

//防止FOwner设置为nil之后相关事件不能触发

TDll(Ptr).DoBeforeDllUnLoaded;

TDll(Ptr).FOwner:=nil;

TDll(Ptr).Free;

end;

end

else

ifAction=lnAddedthen

TDll(Ptr).FOwner:=Self;

inherited;

end;

functionTDllManager.Remove(constFileName:String):Integer;

var

I:Integer;

begin

result:=-1;

Lock;

try

I:=IndexOf(FileName);

ifI>=0then

result:=Remove(Dlls[I])

else

result:=-1;

finally

UnLock;

end;

end;

procedureTDllManager.UnLock;

begin

LeaveCriticalSection(FLock);

OutputDebugString(Pchar(´UnLockDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));

end;

end.

相关阅读
推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
  • 大家都在看
  • 小编推荐
  • 猜你喜欢
  • 最新Delphi学习
    热门Delphi学习
    编程开发子分类