首页 > 代码库 > Delphi捕捉DLL执行所抛出的异常。

Delphi捕捉DLL执行所抛出的异常。

先来说一下我如何写我的Dll文件的。

先看代码:

代码 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->library pub_form;uses  SysUtils,  Classes,  Windows,  Forms,  Parameter_Object,  frm_LoginU in ..\公用库单元\frm_LoginU.pas {frm_Login},  pub_Event in ..\公用库单元\pub_Event.pas,  Dll_LIB_ConstU in ..\公用库单元\Dll_LIB_ConstU.pas;var  DLLApp: TApplication;{begin-----------------------登录窗体相关-------------------------}procedure Login(var mLoginParam: TLoginParam); export;begin  {获取调用窗体的Application,显而易见的功能是 能使你的窗体融合到调用程序中。通过它还能进行很多操作}  Application := mLoginParam.App; //将DLL的Application转为App  if frm_Login = nil then    frm_Login := Tfrm_Login.Create(mLoginParam.ParentForm);  frm_Login.DoLoginClick := mLoginParam.DoLogin;  frm_Login.DoErrCatch:=mLoginParam.ErrDo;  frm_Login.E_User.Text:=mLoginParam.OldUser;  frm_Login.ShowModal;end;procedure CloseLogin; export;begin  if frm_Login.Showing then    frm_Login.Close;end;{end-----------------------登录窗体相关-------------------------}{重写Dll入口函数,否则程序会出错}procedure DLLUnloadProc(Reason: Integer); register;begin  {DLL取消调用时,发送DLL_PROCESS_DETACH消息,此时将DLL的Application返回为本身}  if Reason = DLL_PROCESS_DETACH then Application := DLLApp;end;exports  Login,CloseLogin;begin  {在DLL入口预先储存DLL的Application}  DLLApp := Application;  {DllProc:DLL入口函数指针。Delphi定义为 DllProc: TDLLProc;}  {在此指向我们自己定义的函数}  DLLProc := @DLLUnloadProc;end.

代码中都有注释了,这个不多说了,说一下Login的过程,我这里是直接传递对象指针进来。这个对象的定义在下面的代码中:

代码 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->unit Parameter_Object;{调用DLL的参数对象类}interfaceuses  pub_Event,Forms;type  TDllFormParam=class(TObject)  public    App: TApplication;    ParentForm:TForm;    ErrDo:TExceptionEvent;    constructor CreateByObject(var mApp: TApplication;var mParentForm:TForm;mErrDo:TExceptionEvent);  end;  TLoginParam=class(TDllFormParam)  public    DoLogin:TLoginClickEvent;    OldUser:String;//上次登录的用户    constructor CreateByObject(var mApp: TApplication;var mParentForm:TForm;mErrDo:TExceptionEvent;mDoLogin:TLoginClickEvent;mUser:string=‘‘);  end;implementation{ TLoginParam }constructor TLoginParam.CreateByObject(var mApp: TApplication;   var mParentForm: TForm;mErrDo:TExceptionEvent; mDoLogin: TLoginClickEvent;mUser:string=‘‘);begin  inherited CreateByObject(mApp,mParentForm,mErrDo);  DoLogin:=mDoLogin;  OldUser:=mUser;end;{ TDllFormParam }constructor TDllFormParam.CreateByObject(var mApp: TApplication;  var mParentForm: TForm;mErrDo:TExceptionEvent);begin  App:=mApp;  ParentForm:=mParentForm;  ErrDo:=mErrDo;end;end.

这样做的好处是不用那么多参数出现,也方便动态的调用方式。

还有一个不太重要的单元:

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->unit pub_Event;interfaceuses  SysUtils;type  //点击登录按钮时触发外部检测帐号与密码是否正确  TLoginClickEvent = procedure(UserName, UserPW: string) of object;implementationend.

下面是这个登录传递的源码:

 

代码 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->unit frm_LoginU;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls, pub_Event;type  Tfrm_Login = class(TForm)    E_User: TEdit;    E_PassWD: TEdit;    btn_Login: TButton;    btn_Exit: TButton;    procedure FormKeyPress(Sender: TObject; var Key: Char);    procedure btn_ExitClick(Sender: TObject);    procedure btn_LoginClick(Sender: TObject);    procedure FormClose(Sender: TObject; var Action: TCloseAction);  private    { Private declarations }  public    { Public declarations }    DoLoginClick: TLoginClickEvent;    DoErrCatch:TExceptionEvent;  end;var  frm_Login: Tfrm_Login;implementation{$R *.dfm}procedure Tfrm_Login.FormKeyPress(Sender: TObject; var Key: Char);begin  if key = #13 then  begin    Key := #0;    Keybd_Event(VK_TAB, 0, 0, 0);  end;end;procedure Tfrm_Login.btn_ExitClick(Sender: TObject);begin  self.close;end;procedure Tfrm_Login.btn_LoginClick(Sender: TObject);begin  if Assigned(DoLoginClick) then  begin    try    DoLoginClick(trim(E_User.Text), Trim(E_PassWD.Text));    except   on   e:Exception   do      DoErrCatch(sender,e);    end;  end;end;procedure Tfrm_Login.FormClose(Sender: TObject; var Action: TCloseAction);begin  Action:=caFree;end;end.

 

全部都出来了,我说下我这个DLL的登录验证窗体的工作方式:把登录的验证方法放在主程序里面,因为,不同时期不同的开发项目,其登录验证方式都不一样,因此独立出主程序里,采用回调的方式来实现。由于登录窗体需要到数据库中去验证帐号和密码,因此,我特意把字段输错,这里所报的异常不会被主程序捕捉到,为何不会被主程序捕捉到?我猜是因为调用这个验证方法是一个DLL,而DLL毕竟不是主程序,因此,其错误消息是不会被主程序所捕捉到的,就算开始的时候把application传到了dll里面去也一样捕捉不到(如果能捕捉到的,请把方法告诉我,我找了很久都没找到相关的资料),在网上找了个资料,网址是:

http://www.delphibbs.com/delphibbs/dispq.asp?lid=3660866

根据这个提示,我把异常处理的方法也传进去了,这样,在验证登录方法时出错了,也能调用主程序中的捕捉异常的方法。

 

原创作品出自努力偷懒,转载请说明文章出处:http://www.cnblogs.com/kfarvid/

http://www.cnblogs.com/kfarvid/archive/2010/08/06/1794307.html

 

Delphi捕捉DLL执行所抛出的异常。