插件管理框架 for Delphi(二)

unit untDllManager;

interface

uses

Windows, Classes, SysUtils, Forms;

type

EDllError = Class(Exception);

TDllClass = Class of TDll;

TDll = Class;

TDllEvent = procedure(Sender: TObject; ADll: TDll) of Object;

{ TDllManager

o 提供对 Dll 的管理功能;

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

o Delete 时自动销毁 TDll 对象;

}

TDllManager = Class(TList)

private

FLock: TRTLCriticalSection;

FDllClass: TDllClass;

FOnDllLoad: TDllEvent;

FOnDllBeforeUnLoaded: TDllEvent;

function GetDlls(const Index: Integer): TDll;

function GetDllsByName(const FileName: String): TDll;

protected

procedure Notify(Ptr: Pointer; Action: TListNotification); override;

public

constructor Create;

destructor Destroy; override;

function Add(const FileName: String): Integer; overload;

function IndexOf(const FileName: String): Integer; overload;

function Remove(const FileName: String): Integer; overload;

procedure Lock;

procedure UnLock;

property DllClass: TDllClass read FDllClass write FDllClass;

property Dlls[const Index: Integer]: TDll read GetDlls; default;

property DllsByName[const FileName: String]: TDll read GetDllsByName;

property OnDllLoaded: TDllEvent read FOnDllLoad write FOnDllLoad;

property OnDllBeforeUnLoaded: TDllEvent read FOnDllBeforeUnLoaded write FOnDllBeforeUnLoaded;

end;

{ TDll

o 代表一个 Dll, Windows.HModule

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

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

}

TDll = Class(TObject)

private

FOwner: TDllManager;

FModule: HMODULE;

FFileName: String;

FPermit: Boolean;

procedure SetFileName(const Value: String);

function GetLoaded: Boolean;

procedure SetLoaded(const Value: Boolean);

procedure SetPermit(const Value: Boolean);

protected

procedure DoDllLoaded; virtual;

procedure DoBeforeDllUnLoaded; virtual;

procedure DoDllUnLoaded; virtual;

procedure DoFileNameChange; virtual;

procedure DoPermitChange; virtual;

public

constructor Create; virtual;

destructor Destroy; override;

function GetProcAddress(const Order: Longint): FARPROC; overload;

function GetProcAddress(const ProcName: String): FARPROC; overload;

property FileName: String read FFileName write SetFileName;

property Loaded: Boolean read GetLoaded write SetLoaded;

property Owner: TDllManager read FOwner;

property Permit: Boolean read FPermit write SetPermit;

end;

implementation

{ TDll }

constructor TDll.Create;

begin

FOwner := nil;

FFileName := ´´;

FModule := 0;

FPermit := True;

end;

destructor TDll.Destroy;

var

Manager: TDllManager;

begin

Loaded := False;

if FOwner <> nil then

begin

//在拥有者中删除自身

Manager := FOwner;

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

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

//才能确保正确。

FOwner := nil;

Manager.Remove(Self);

end;

inherited;

end;

function TDll.GetLoaded: Boolean;

begin

result := FModule <> 0;

end;

function TDll.GetProcAddress(const Order: Longint): FARPROC;

begin

if Loaded then

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

else

raise EDllError.CreateFmt(´Do Load before GetProcAddress of "%u"´, [DWORD(Order)]);

end;

function TDll.GetProcAddress(const ProcName: String): FARPROC;

begin

if Loaded then

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

else

raise EDllError.CreateFmt(´Do Load before GetProcAddress of "%s"´, [ProcName]);

end;

procedure TDll.SetLoaded(const Value: Boolean);

begin

if Loaded <> Value then

begin

if not Value then

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

On E: Exception do

begin

if FModule <> 0 then

begin

FreeLibrary(FModule);

FModule := 0;

end;

raise EDllError.CreateFmt(´LoadLibrary Error: %s´, [E.Message]);

end;

end;

end;

end;

end;

procedure TDll.SetFileName(const Value: String);

begin

if Loaded then

raise EDllError.CreateFmt(´Do Unload before load another Module named: "%s"´,

[Value]);

if FFileName <> Value then

begin

FFileName := Value;

DoFileNameChange;

end;

end;

procedure TDll.DoFileNameChange;

begin

// do nonthing.

end;

procedure TDll.DoDllLoaded;

begin

if Assigned(FOwner) and Assigned(FOwner.OnDllLoaded) then

FOwner.OnDllLoaded(FOwner, Self);

end;

procedure TDll.DoDllUnLoaded;

begin

//do nonthing.

end;

procedure TDll.DoPermitChange;

begin

//do nonthing.

end;

procedure TDll.SetPermit(const Value: Boolean);

begin

if FPermit <> Value then

begin

FPermit := Value;

DoPermitChange;

end;

end;

procedure TDll.DoBeforeDllUnLoaded;

begin

if Assigned(FOwner) and Assigned(FOwner.OnDllBeforeUnLoaded) then

FOwner.OnDllBeforeUnLoaded(FOwner, Self);

end;

{ TDllManager }

function TDllManager.Add(const FileName: String): Integer;

var

Dll: TDll;

begin

result := -1;

Lock;

try

if DllsByName[FileName] = nil then

begin

Dll := FDllClass.Create;

Dll.FileName := FileName;

result := Add(Dll);

end

else

result := -1;

finally

UnLock;

end;

end;

constructor TDllManager.Create;

begin

FDllClass := TDll;

InitializeCriticalSection(FLock);

end;

destructor TDllManager.Destroy;

begin

DeleteCriticalSection(FLock);

inherited;

end;

function TDllManager.GetDlls(const Index: Integer): TDll;

begin

Lock;

try

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

result := Items[Index]

else

raise EDllError.CreateFmt(´Error Index of GetDlls, Value: %d, Total Count: %d´, [Index, Count]);

finally

UnLock;

end;

end;

function TDllManager.GetDllsByName(const FileName: String): TDll;

var

I: Integer;

begin

Lock;

try

I := IndexOf(FileName);

if I >= 0 then

result := Dlls[I]

else

result := nil;

finally

UnLock;

end;

end;

function TDllManager.IndexOf(const FileName: String): Integer;

var

I: Integer;

begin

result := -1;

Lock;

try

for I := 0 to Count - 1 do

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

begin

result := I;

break;

end;

finally

UnLock;

end;

end;

procedure TDllManager.Lock;

begin

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

EnterCriticalSection(FLock);

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

end;

procedure TDllManager.Notify(Ptr: Pointer; Action: TListNotification);

begin

if Action = lnDeleted then

begin

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

//表明由 TDll.Destroy 触发;

if TDll(Ptr).Owner = Self then

begin

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

TDll(Ptr).DoBeforeDllUnLoaded;

TDll(Ptr).FOwner := nil;

TDll(Ptr).Free;

end;

end

else

if Action = lnAdded then

TDll(Ptr).FOwner := Self;

inherited;

end;

function TDllManager.Remove(const FileName: String): Integer;

var

I: Integer;

begin

result := -1;

Lock;

try

I := IndexOf(FileName);

if I >= 0 then

result := Remove(Dlls[I])

else

result := -1;

finally

UnLock;

end;

end;

procedure TDllManager.UnLock;

begin

LeaveCriticalSection(FLock);

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

end;

end.

(0)

相关推荐

  • 插件管理框架 for Delphi(二)

    unit untDllManager; interface uses Windows, Classes, SysUtils, Forms; type EDllError = Class(Exception); TDllClass = Class of TDll; TDll = Class; TDllEvent = procedure(Sender: TObject; ADll: TDll) of Object; { TDllManager o 提供对 Dll 的管理功能: o Add 时自动创建

  • 插件管理框架 for Delphi(一)

    插件技术的出发点主要是为了使软件能够灵活地进行扩展功能,而不需要对主程序(框架程序)进行重新编译和发布.它的原理相当简单.软件的功能由框架程序和插件来决定.在框架程序和插件之间具有一个特定的接口,它们两者须通过这个接口来传递数据或控制信息,以实现软件功能.因此,只要符合该接口的程序(或其他功能实体),就称为该框架程序的插件.插件实体一般分为两种,一种是包含逻辑的程序,比如动态库.Exe程序等:另一种则是一组配置信息.前一种方式多见于作图软件,媒体播放软件,适合实现复杂的功能:后一种方式多用于实现

  • jquery插件qrcode在线生成二维码

    随着移动互联网的发展,二维码现在应用得越来越广泛了,随手扫扫就可以浏览网站.加个好友什么的,比起手工输入真的是方便太多了. 前期做了一个综合测评系统,考虑逐步实现移动化,一长串的IP地址用户输入也不方便,借助二维码的话,用户拿起手机扫扫就可以直接进入系统. 基于这个应用场景,就上网研究下了网站二维码的实现方式,归纳起来有以下两种: 1.借助一些二维码生成网站或者二维码生成器生成二维码图片,然后挂在网站上,如码云 QR-Code (二维码) 在线生成器 优点:开发成本为零,能够快速实现多样化的二维

  • 使用JS 插件qrcode.js生成二维码功能

    效果图: qrcode.js这是一个使用比较多的js生成二维码的插件,使用也很方便,第一次用,记录一下使用方法: 首先,导入js,这个网上可以找到,附上地址:https://github.com/davidshimjs/qrcodejs/ jsp: <script type="text/javascript" src="<%=basePath %>bootstrap/js/qrcode.js" charset="UTF-8"&g

  • 非常有用的40款jQuery 插件推荐(系列二)

    今天开始将发布系列文章向大家分享40款非常有用的 jQuery 插件. HTML5 File Uploads with jQuery ( 演示 | 下载 ) 这是一款用于帮助你实现 HTML5 文件拖放上传功能的 jQuery 插件. Shuffle Letters Effect: a jQuery Plugin ( 演示 | 下载 ) 这款插件能够帮助实现非常酷的文字显示效果,可用于标题.LOGO和幻灯片. Skitter ( 演示 | 下载 ) Skitter 是一款非常精美的幻灯片插件,可

  • typecho插件编写教程(二):写一个新插件

    第一节我们了解了一个插件的基本构成,下面我们需要一个实例练习巩固. 真赶巧,老高最近正在改版百度sitemap提交插件for typecho,下面和老高一起改版吧! 准备 不知道大家用过WP版的百度结构化插件没?老高就是研究了那个插件,观察其API,然后就写出了typecho版的. 为什么要改版呢? 百度站长最近推出新的接口,使用起来更简单,工作量不算大,索性就改改吧! 新版插件需要实现哪些功能? 1.文章实时推送 2.推送历史数据 3.站点地图 接口调用地址(API)在哪儿? 百度站长后台,P

  • 40个有创意的jQuery图片和内容滑动及弹出插件收藏集之二

    在网页的首页或图片专题页面很多地方都会用到图片滑动插件来循环切换多张图片,并且用户可以点击左右按钮来切换图片.相信大家都知道jQuery是最优秀的Javascript框架之一.以其语法简单灵活而大受Web designer欢迎.所以很多网页设计师结合jQuery的强大功能制作出了许多成熟的图片滑动插件,我们可以很简单地直接将这些图片滑动插件嵌入到网页中,很容易就得到了即酷又实用的jQuery图片滑动效果.在这是jQuery滑动切换插件系列的第二篇,我们将向大家分享40多种非常有用,又有创意的jQ

  • 几个优化WordPress中JavaScript加载体验的插件介绍

    WordPress 本身以及主题和插件通常需要加载一些 JavaScript 来实现某些特殊功能.为了最大限度地保证兼容性,不至于出现 JavaScript 失效的情况,所以一般在页头加载 JavaScript 文件.但是根据 Yahoo 开发者论坛的建议,加载 JavaScript 应该尽量在页尾以提高页面的显示(响应.渲染)速度.本文根据作者的使用经验介绍几个相关插件,并说明如何在某些特殊页面仍然在页头加载 JavaScript. 下面先简单介绍几个相关的优化 JavaScript 的 Wo

  • jQuery表单验证插件解析(推荐)

    一:插件 (1) Validform_v5.3.1_min.js Validform_Datatype.js (2)网址:http://validform.rjboy.cn 在这个网站上有demo和插件下载链接. 二:普通验证 (1)Validform_Datatype.js /* Validform datatype extension By sean during December 8, 2012 - February 20, 2013 For more information, pleas

  • 11行JS代码制作二维码生成功能

    HTML代码: <img style="display: none" id="qrcode" data-width="100" data-height="100" data-url="https://www.baidu.com/"> 相关JS代码: /** * 生成二维码 * data-width={宽度} * data-height={高度} * data-url={链接} * @param

随机推荐