先来说一下我如何写我的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 = # then
begin
Key := #;
Keybd_Event(VK_TAB, , , );
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执行所抛出的异常。的更多相关文章

  1. 捕获Java线程池执行任务抛出的异常

    捕获Java线程池执行任务抛出的异常Java中线程执行的任务接口java.lang.Runnable 要求不抛出Checked异常, public interface Runnable { publi ...

  2. 想抛就抛:Application_Error中统一处理ajax请求执行中抛出的异常

    女朋友不是想抛就抛,但异常却可以,不信请往下看. 今天在MVC Controller中写代码时,纠结了一下: public async Task<ActionResult> Save(in ...

  3. 外部无法捕捉Realm的doGetAuthenticationInfo方法抛出的异常

    shiro权限框架,用户登录方法的subject.login(token)会进入自定义的UserNamePasswordRealm类的doGetAuthenticationInfo身份验证方法 通常情 ...

  4. 应该抛出什么异常?不应该抛出什么异常?(.NET/C#)

    我在 .NET/C# 建议的异常处理原则 中描述了如何 catch 异常以及重新 throw.然而何时应该 throw 异常,以及应该 throw 什么异常呢? 究竟是谁错了? 代码中从上到下从里到外 ...

  5. druid抛出的异常------javax.management.InstanceAlreadyExistsException引发的一系列探索

    最近项目中有个定时任务的需求,定时检查mysql数据与etcd数据的一致性,具体实现细节就不说了,今天要说的就是实现过程中遇到了druid抛出的异常,以及解决的过程 异常 异常详细信息 五月 05, ...

  6. Java中主线程如何捕获子线程抛出的异常

    首先明确线程代码的边界.其实很简单,Runnable接口的run方法所界定的边界就可以看作是线程代码的边界.Runnable接口中run方法原型如下: public void run(); 而所有的具 ...

  7. 记录一次dubbo不能正常抛出特定异常

    BUG场景 今天同事的代码中出现一个问题,让我帮忙排查一下.原代码大致如下 dubbo服务消费者: @Resource private IPayWayService payWayService; @R ...

  8. 将Controller抛出的异常转到特定View

    <!-- 将Controller抛出的异常转到特定View --> <bean class="org.springframework.web.servlet.handler ...

  9. 使用visual studio 2015调用阿里云oss .net sdk 2.2的putobject接口抛出outofmemory异常

    问题描述: 使用阿里云oss .net sdk 2.2版本,使用putobject接口上传文件时,抛出outofmemory异常. 原因分析: 上传时,用于准备上传的数据缓冲区内存分配失败.与应用软件 ...

随机推荐

  1. Android MVP架构浅析

    Android之MVC模式 MVC好处: 从用户的角度出发,用户可以根据自己的需求,选择自己合适的浏览数据的方式.比如说,对于一篇在线文档,用户可以选择以HTML网页的方式阅读,也可以选择以pdf的方 ...

  2. SpringMVC学习记录

    1E)Spring MVC框架 ①Jar包结构: docs+libs+schema. 版本区别:核心包,源码包. SpringMVC文档学习: 学习三步骤: 1)是什么? 开源框架 2)做什么? IO ...

  3. Oracle学习第一天---安装和基础入门

    国庆七天假,决定静下心来入门Oracle数据库. 环境:Ocacle 11g 软件安装包和安装图解,大家可以在我的百度网盘上下载:链接:http://pan.baidu.com/s/1ntjDEnZ ...

  4. 永久设置 NLS_DATE_FORMAT 方法

    在客户端(如WEB服务器),设置环境变量即可,如: NLS_DATE_FORMAT YYYY-MM-DD HH24:MI:SS   在程序处执行会影响后续SQL性能 ALTER SESSION SET ...

  5. ### 学习《C++ Primer》- 8

    Part 8: 面向对象(第15章) // @author: gr // @date: 2015-01-09 // @email: forgerui@gmail.com 一.OOP 面向对象程序设计的 ...

  6. iOS-深复制(mutableCopy)与浅复制(copy)

    浅复制:只复制指向对象的指针,而不复制引用对象本身.对于浅复制来说,A和A_copy指向的是同一个内存资源,复制的只是一个指针,对象本身资源还是只有一份(对象引用计数+1),那如果我们对A_copy执 ...

  7. jQuery 源码分析6: jQuery 基本静态方法(二)

    jQuery.extend({ // 遍历obj的所有值 // args 这参数只能内部调用的会用到 // 注意到,如果回调函数调用失败会直接跳出并中止遍历 // 当有args数组时,使用apply调 ...

  8. Mysql的联合查询

    联合查询 union联合查询 语法:     select 语句 union [all|distinct] select 语句; 示例: 特点:     条件:两表的查询出来的字段数目必须相同     ...

  9. myeclipse 右键 Add Struts... 页面报404 错误

    网上试了很多种方法都不对,结果老师两下点出来了 我的改正方法是: 将WebRoot/WEB-INF/web.xml中的 <url-pattern>/*</url-pattern> ...

  10. JS中undefined和null的区别

    在写JS脚本的时候,经常会碰到“为空”的判断,其中主要有null和undefined的判断.这两个为空判断的主要区别是: 1) null是JS的关键字,是语法特性.undefined是全局对象的属性, ...