unituntDllManager;
antarmuka
kegunaan
Windows, Kelas, SysUtils, Formulir;
jenis
EDllError=Kelas(Pengecualian);
TDllClass=KelasTDll;
TDll=Kelas;
TDllEvent=prosedur(Pengirim:TObject;ADll:TDll)ofObject;
{Manajer TDll
o提供对Dll的管理功能;
oTambahkan TDll对象,但不尝试装载;
oHapus时自动销毁TDll对象;
}
TDllManager=Kelas(Daftar T)
pribadi
Kawanan: TRTLC Bagian Kritis;
Kelas FDll:Kelas TDll;
FOnDllLoad:TDllEvent;
FOnDllBeforeUnLoaded:TDllEvent;
functionGetDlls(constIndex:Integer):TDll;
functionGetDllsByName(constFileName:String):TDll;
terlindung
procedureNotify(Ptr:Pointer;Action:TListNotification);override;
publik
konstruktorBuat;
destructorHancurkan;timpa;
functionAdd(constFileName:String):Integer;kelebihan beban;
functionIndexOf(constFileName:String):Integer;kelebihan beban;
functionRemove(constFileName:String):Integer;kelebihan beban;
kunci prosedur;
prosedurBuka Kunci;
propertyDllClass:TDllClassreadFDllClasswriteFDllClass;
propertyDlls[constIndex:Integer]:TDllreadGetDlls;default;
propertyDllsByName[constFileName:String]:TDllreadGetDllsByName;
propertyOnDllLoaded:TDllEventreadFOnDllLoadwriteFOnDllLoad;
propertyOnDllBeforeUnLoaded:TDllEventreadFOnDllBeforeUnLoadedwriteFOnDllBeforeUnLoaded;
akhir;
{Tdll
o代表一个Dll,Windows.HModule
o销毁时自动在Pemilik中删除自身;
o melakukan overrideDoDllLoaded, atau DoDllUnLoaded, dan melakukan overrideDoDllLoaded;
}
TDll=Kelas(TObjek)
pribadi
Pemilik: Manajer TDll;
Modul FM: HMODULE;
NamaFile:String;
Izin F: Boolean;
procedureSetFileName(constValue:String);
functionGetLoaded:Boolean;
procedureSetLoaded(constValue:Boolean);
procedureSetPermit(constValue:Boolean);
terlindung
procedureDoDllLoaded;virtual;
procedureDoBeforeDllUnLoaded;virtual;
procedureDoDllUnLoaded;virtual;
procedureDoFileNameChange;virtual;
procedureDoPermitChange;virtual;
publik
konstruktorBuat;virtual;
destructorHancurkan;timpa;
functionGetProcAddress(constOrder:Longint):FARPROC;kelebihan beban;
functionGetProcAddress(constProcName:String):FARPROC;kelebihan beban;
propertyFileName:StringreadFFileNamewriteSetFileName;
propertyLoaded:BooleanreadGetLoadedwriteSetLoaded;
Pemilik Properti:TDllManagerreadFOwner;
propertyPermit:BooleanreadFPermitwriteSetPermit;
akhir;
pelaksanaan
{TDll}
konstruktorTDll.Buat;
mulai
Pemilik:=nihil;
Nama File F:=´´;
Modul FM:=0;
Izin F:=Benar;
akhir;
destructorTDll.Destroy;
var
Manajer: Manajer TDll;
mulai
Dimuat:=Salah;
ifFOwner<>nilthen
mulai
//在拥有者中删除自身
Manajer:=Pemilik;
//未防止在TDllManager中重复删除,因此需要将
//FOwner设置为nil;<--此段代码和TDllManager.Notify需要配合
//才能确保正确。
Pemilik:=nihil;
Manajer.Hapus(Diri);
akhir;
diwariskan;
akhir;
functionTDll.GetLoaded:Boolean;
mulai
hasil:=FModule<>0;
akhir;
functionTDll.GetProcAddress(constOrder:Longint):FARPROC;
mulai
jika Dimuat maka
hasil:=Windows.GetProcAddress(FModule,Pointer(Order))
kalau tidak
raiseEDllError.CreateFmt(´DoLoadbeforeGetProcAddressof%u´,[DWORD(Pesanan)]);
akhir;
functionTDll.GetProcAddress(constProcName:String):FARPROC;
mulai
jika Dimuat maka
hasil:=Windows.GetProcAddress(FModule,PChar(ProcName))
kalau tidak
raiseEDllError.CreateFmt(´DoLoadbeforeGetProcAddressof%s´,[ProcName]);
akhir;
procedureTDll.SetLoaded(constValue:Boolean);
mulai
ifLoaded<>Nilailalu
mulai
jika tidakNilailalu
mulai
Tegaskan(FModul<>0);
LakukanSebelumDllDibongkar;
mencoba
Perpustakaan Gratis (FModule);
Modul FM:=0;
kecuali
Aplikasi.HandleException(Diri);
akhir;
LakukanDllTidak Dimuat;
akhir
kalau tidak
mulai
FModule:=LoadLibrary(PChar(FFileName));
mencoba
Win32Check(FModul<>0);
LakukanDllDimuat;
kecuali
Satu: Pengecualian
mulai
ifFModule<>0lalu
mulai
Perpustakaan Gratis (FModule);
Modul FM:=0;
akhir;
raiseEDllError.CreateFmt(´LoadLibraryError:%s´,[E.Message]);
akhir;
akhir;
akhir;
akhir;
akhir;
procedureTDll.SetFileName(constValue:String);
mulai
jika Dimuat maka
raiseEDllError.CreateFmt(´DoUnloadbeforeloadanotherModulenname:%s´,
[Nilai]);
ifFFileName<>Nilailalu
mulai
FFileName:=Nilai;
DoFileNameChange;
akhir;
akhir;
procedureTDll.DoFileNameChange;
mulai
//tidak melakukan apa pun.
akhir;
procedureTDll.DoDllLoaded;
mulai
ifAssigned(FOwner)andAssigned(FOwner.OnDllLoaded)lalu
FOwner.OnDllLoaded(FOwner,Self);
akhir;
procedureTDll.DoDllUnLoaded;
mulai
//tidak melakukan apa pun.
akhir;
procedureTDll.DoPermitChange;
mulai
//tidak melakukan apa pun.
akhir;
procedureTDll.SetPermit(constValue:Boolean);
mulai
ifFPermit<>Nilailalu
mulai
Izin F:=Nilai;
DoPermitChange;
akhir;
akhir;
procedureTDll.DoBeforeDllUnLoaded;
mulai
ifAssigned(FOwner)andAssigned(FOwner.OnDllBeforeUnLoaded)lalu
FOwner.OnDllBeforeUnLoaded(FOwner,Self);
akhir;
{Manajer TDll}
functionTDllManager.Add(constFileName:String):Integer;
var
Dll:TDll;
mulai
hasil:=-1;
Kunci;
mencoba
ifDllsByName[Nama File]=nilthen
mulai
Dll:=FDllClass.Create;
Dll.Nama File:=Nama File;
hasil:=Tambah(Dll);
akhir
kalau tidak
hasil:=-1;
Akhirnya
Membuka kunci;
akhir;
akhir;
konstruktorTDllManager.Buat;
mulai
Kelas FDll:=TDll;
InisialisasiCriticalSection (FLock);
akhir;
destructorTDllManager.Destroy;
mulai
HapusBagianKritikal(FLock);
diwariskan;
akhir;
functionTDllManager.GetDlls(constIndex:Integer):TDll;
mulai
Kunci;
mencoba
jika(Indeks>=0)dan(Indeks<=Hitungan-1)maka
hasil:=Item[Indeks]
kalau tidak
raiseEDllError.CreateFmt(´ErrorIndexofGetDlls,Nilai:%d,TotalCount:%d´,[Indeks,Hitungan]);
Akhirnya
Membuka kunci;
akhir;
akhir;
functionTDllManager.GetDllsByName(constFileName:String):TDll;
var
Saya: Bilangan Bulat;
mulai
Kunci;
mencoba
I:=IndexOf(NamaFile);
jikaSaya>=0maka
hasil:=Dll[I]
kalau tidak
hasil:=nihil;
Akhirnya
Membuka kunci;
akhir;
akhir;
functionTDllManager.IndexOf(constFileName:String):Integer;
var
Saya: Bilangan Bulat;
mulai
hasil:=-1;
Kunci;
mencoba
forI:=0toCount-1do
ifCompareText(NamaFile,Dlls[I].NamaFile)=0lalu
mulai
hasil:=Saya;
merusak;
akhir;
Akhirnya
Membuka kunci;
akhir;
akhir;
procedureTDllManager.Lock;
mulai
OutputDebugString(Pchar(´TRLockDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));
EnterCriticalSection (FLock);
OutputDebugString(Pchar(´LockedDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));
akhir;
procedureTDllManager.Notify(Ptr:Pointer;Action:TListNotification);
mulai
ifAction=lnDeletedthen
mulai
//若TDll(Ptr).Pemilik和Self不同,则
//表明由TDll.Hancurkan触发;
ifTDll(Ptr).Pemilik=Selfthen
mulai
//防止FOwner设置为nil之后相关事件不能触发
TDll(Ptr).DoBeforeDllUnloaded;
TDll(Ptr).FOwner:=nihil;
TDll(Ptr).Gratis;
akhir;
akhir
kalau tidak
ifAction=lnDitambahkanlalu
TDll(Ptr).FOwner:=Diri;
diwariskan;
akhir;
functionTDllManager.Remove(constFileName:String):Integer;
var
Saya: Bilangan Bulat;
mulai
hasil:=-1;
Kunci;
mencoba
I:=IndexOf(NamaFile);
jikaSaya>=0maka
hasil:=Hapus(Dll[I])
kalau tidak
hasil:=-1;
Akhirnya
Membuka kunci;
akhir;
akhir;
procedureTDllManager.Unlock;
mulai
Tinggalkan Bagian Kritis (Kawanan);
OutputDebugString(Pchar(´UnLockDM´+IntToStr(GetCurrentThreadId)+´:´+IntToStr(DWORD(Self))));
akhir;
akhir.