unituntDllManager;
интерфейс
использует
Windows, классы, SysUtils, формы;
тип
EDllError=Класс(Исключение);
TDllClass=КлассTDll;
TDll=Класс;
TDllEvent = процедура (Отправитель: TObject; ADll: TDll) ofObject;
{TDllManager
o提供对Dll的管理功能;
oAdd时自动创建TDll对象,但不尝试装载;
oУдалить файлы TDll и файлы;
}
TDllManager=Класс(TList)
частный
FLock:TRTLCriticalSection;
ФДллкласс:Тдллкласс;
FOnDllLoad:TDllEvent;
FOnDllBeforeUnLoaded:TDllEvent;
functionGetDlls(constIndex:Integer):TDll;
functionGetDllsByName (constFileName: String): TDll;
защищенный
процедураNotify(Ptr:Pointer;Action:TListNotification);override;
общественный
конструкторСоздать;
деструкторDestroy;переопределить;
functionAdd(constFileName:String):Целое число;перегрузка;
functionIndexOf(constFileName:String):Целое число;перегрузка;
functionRemove(constFileName:String):Целое число;перегрузка;
процедураLock;
процедураUnLock;
propertyDllClass:TDllClassreadFDllClasswriteFDllClass;
propertyDlls[constIndex:Integer]:TDllreadGetDlls;default;
propertyDllsByName[constFileName:String]:TDllreadGetDllsByName;
propertyOnDllLoaded:TDllEventreadFOnDllLoadwriteFOnDllLoad;
propertyOnDllBeforeUnLoaded:TDllEventreadFOnDllBeforeUnLoadedwriteFOnDllBeforeUnLoaded;
конец;
{TDll
o 代表一个Dll,Windows.HModule
o销毁时自动在Владелец中删除自身;
o переопределить DoDllLoaded, DoDllUnLoaded или переопределить DoDllUnLoaded;
}
TDll=Класс(TObject)
частный
FOwner:TDllManager;
ФМодуль: ХМОДУЛЬ;
FFileName:Строка;
FPermit:Boolean;
процедураSetFileName (constValue: String);
functionGetLoaded:Boolean;
процедураSetLoaded (constValue: Boolean);
процедураSetPermit (constValue: Boolean);
защищенный
процедураDoDllLoaded;виртуальный;
процедураDoBeforeDllUnLoaded;виртуальный;
процедураDoDllUnLoaded;виртуальный;
процедураDoFileNameChange;виртуальный;
процедураDoPermitChange;виртуальный;
общественный
конструкторCreate;виртуальный;
деструкторDestroy;переопределить;
functionGetProcAddress(constOrder:Longint):FARPROC;перегрузка;
functionGetProcAddress(constProcName:String):FARPROC;перегрузка;
propertyFileName: StringreadFFileNamewriteSetFileName;
propertyLoaded:BooleanreadGetLoadedwriteSetLoaded;
propertyOwner:TDllManagerreadFOwner;
propertyPermit: BooleanreadFPermitwriteSetPermit;
конец;
выполнение
{TDll}
конструкторTDll.Создать;
начинать
Владелец:=ноль;
FFileName:=´´;
ФМодуль:=0;
ФПермит:=Истина;
конец;
деструкторTDll.Уничтожить;
вар
Менеджер:TDllManager;
начинать
Загружено: = Ложь;
ifFOwner<>nilthen
начинать
//在拥有者中删除自身
Менеджер:=FOowner;
//Поддержка TDllManager中重复删除, 因此需要将
//FOwner设置为nil;<--此段代码和TDllManager.Notify需要配合
//才能确保正确。
Владелец:=ноль;
Менеджер.Удалить(Self);
конец;
унаследованный;
конец;
functionTDll.GetLoaded:Boolean;
начинать
результат:=FModule<>0;
конец;
functionTDll.GetProcAddress(constOrder:Longint):FARPROC;
начинать
еслиLoadedthen
результат: = Windows.GetProcAddress(FModule,Pointer(Order))
еще
поднятьEDllError.CreateFmt(´DoLoadbeforeGetProcAddressof%u´,[DWORD(Order)]);
конец;
functionTDll.GetProcAddress(constProcName:String):FARPROC;
начинать
еслиLoadedthen
результат: = Windows.GetProcAddress(FModule,PChar(ProcName))
еще
поднятьEDllError.CreateFmt(´DoLoadbeforeGetProcAddressof%s´,[ProcName]);
конец;
процедураTDll.SetLoaded(constValue:Boolean);
начинать
ifLoaded<>Valuethen
начинать
если не значение, то
начинать
Утверждать (FModule<>0);
Добефоредллуунлоадед;
пытаться
Бесплатная библиотека (FМодуль);
ФМодуль:=0;
кроме
Application.HandleException(Self);
конец;
DoDllUnLoaded;
конец
еще
начинать
FModule:=LoadLibrary(PChar(FFileName));
пытаться
Win32Check(FModule<>0);
DoDllLoaded;
кроме
OneE:Исключение
начинать
еслиFМодуль<>0тогда
начинать
Бесплатная библиотека (FМодуль);
ФМодуль:=0;
конец;
поднятьEDllError.CreateFmt(´LoadLibraryError:%s´,[E.Message]);
конец;
конец;
конец;
конец;
конец;
процедураTDll.SetFileName(constValue:String);
начинать
еслиLoadedthen
поднятьEDllError.CreateFmt(´DoUnloadbeforeloadanotherModulenamed:%s´,
[Ценить]);
еслиFFileName<>Значение, то
начинать
FFileName:=Значение;
DoFileNameChange;
конец;
конец;
процедураTDll.DoFileNameChange;
начинать
// ничего не делать.
конец;
процедураTDll.DoDllLoaded;
начинать
еслиНазначено(FOwner)иНазначено(FOwner.OnDllLoaded),то
FOwner.OnDllLoaded(FOwner,Self);
конец;
процедураTDll.DoDllUnLoaded;
начинать
// ничего не делать.
конец;
процедураTDll.DoPermitChange;
начинать
// ничего не делать.
конец;
процедураTDll.SetPermit(constValue:Boolean);
начинать
ifFPermit<>Valuethen
начинать
FPermit:=Значение;
ДоПермитЧанге;
конец;
конец;
процедураTDll.DoBeforeDllUnLoaded;
начинать
еслиНазначено(FOwner)иНазначено(FOwner.OnDllBeforeUnLoaded),то
FOwner.OnDllBeforeUnLoaded(FOwner,Self);
конец;
{TDllManager}
functionTDllManager.Add(constFileName:String):Integer;
вар
Длл:ТДлл;
начинать
результат:=-1;
Замок;
пытаться
ifDllsByName[FileName]=nilthen
начинать
Dll:=FDllClass.Create;
Dll.FileName:=FileName;
результат: = Добавить (Dll);
конец
еще
результат:=-1;
окончательно
Разблокировать;
конец;
конец;
конструкторTDllManager.Create;
начинать
FDllClass:=TDll;
ИнициализироватьКритическийРаздел(FLock);
конец;
деструкторTDllManager.Destroy;
начинать
УдалитьКритическийРаздел(FLock);
унаследованный;
конец;
functionTDllManager.GetDlls(constIndex:Integer):TDll;
начинать
Замок;
пытаться
если (Индекс>=0) и (Индекс<=Count-1), то
результат:=Предметы[Индекс]
еще
поднятьEDllError.CreateFmt(´ErrorIndexofGetDlls,Value:%d,TotalCount:%d´,[Index,Count]);
окончательно
Разблокировать;
конец;
конец;
functionTDllManager.GetDllsByName(constFileName:String):TDll;
вар
Я: целое число;
начинать
Замок;
пытаться
Я:=IndexOf(ИмяФайла);
еслиI>=0то
результат:=Dlls[I]
еще
результат: = ноль;
окончательно
Разблокировать;
конец;
конец;
functionTDllManager.IndexOf(constFileName:String):Integer;
вар
Я: целое число;
начинать
результат:=-1;
Замок;
пытаться
forI:=0toCount-1do
ifCompareText(FileName,Dlls[I].FileName)=0then
начинать
результат:=Я;
перерыв;
конец;
окончательно
Разблокировать;
конец;
конец;
процедура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:=ноль;
TDll(Ptr).Бесплатно;
конец;
конец
еще
ifAction=lnAddedthen
TDll(Ptr).FOwner:=Self;
унаследованный;
конец;
functionTDllManager.Remove(constFileName:String):Integer;
вар
Я: целое число;
начинать
результат:=-1;
Замок;
пытаться
Я:=IndexOf(ИмяФайла);
еслиI>=0то
результат:=Удалить(Dlls[I])
еще
результат:=-1;
окончательно
Разблокировать;
конец;
конец;
процедураTDllManager.UnLock;
начинать
LeaveCriticalSection(FLock);
OutputDebugString(Pchar(´UnLockDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));
конец;
конец.