zoukankan      html  css  js  c++  java
  • 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的参数对象类
    
    }
    
    interface
    uses
      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;
    
    interface
    uses
      SysUtils;
    
    type
      //点击登录按钮时触发外部检测帐号与密码是否正确
      TLoginClickEvent = procedure(UserName, UserPW: string) of object;
    
    implementation
    
    end.

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

    代码 
    
    Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->unit frm_LoginU;
    
    interface
    
    uses
      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

  • 相关阅读:
    为什么世界上没有安全的工作?
    GIT学习----第六节:撤销修改
    vue-cli中koa输出console.log报错的解决方案
    简易版promise源码实现
    bind函数的模拟实现
    Es6语法实现的转盘抽奖效果——可配置转盘的抽奖概率
    探寻Object.assign内部的奥秘
    promise基本使用——简单的运动效果
    数组sort方法源码解析
    ES5数组一些常用的方法源码实现
  • 原文地址:https://www.cnblogs.com/findumars/p/5951306.html
Copyright © 2011-2022 走看看