Delphi捕捉DLL执行所抛出的异常。
先來說一下我如何寫我的Dll文件的。
先看代碼:
?
代碼 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-----------------------登錄窗體相關(guān)-------------------------}
procedure?Login(var?mLoginParam:?TLoginParam);?export;
begin
??{獲取調(diào)用窗體的Application,顯而易見的功能是?能使你的窗體融合到調(diào)用程序中。通過它還能進(jìn)行很多操作}
??Application?:=?mLoginParam.App;?//將DLL的Application轉(zhuǎn)為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-----------------------登錄窗體相關(guān)-------------------------}
{重寫Dll入口函數(shù),否則程序會出錯}
procedure?DLLUnloadProc(Reason:?Integer);?register;
begin
??{DLL取消調(diào)用時,發(fā)送DLL_PROCESS_DETACH消息,此時將DLL的Application返回為本身}
??if?Reason?=?DLL_PROCESS_DETACH?then?Application?:=?DLLApp;
end;
exports
??Login,CloseLogin;
begin
??{在DLL入口預(yù)先儲存DLL的Application}
??DLLApp?:=?Application;
??{DllProc:DLL入口函數(shù)指針。Delphi定義為?DllProc:?TDLLProc;}
??{在此指向我們自己定義的函數(shù)}
??DLLProc?:=?@DLLUnloadProc;
end.
?
代碼中都有注釋了,這個不多說了,說一下Login的過程,我這里是直接傳遞對象指針進(jìn)來。這個對象的定義在下面的代碼中:
?
代碼 unit?Parameter_Object;{
調(diào)用DLL的參數(shù)對象類
}
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.
?
?
這樣做的好處是不用那么多參數(shù)出現(xiàn),也方便動態(tài)的調(diào)用方式。
還有一個不太重要的單元:
?
unit?pub_Event;interface
uses
??SysUtils;
type
??//點擊登錄按鈕時觸發(fā)外部檢測帳號與密碼是否正確
??TLoginClickEvent?=?procedure(UserName,?UserPW:?string)?of?object;
implementation
end.
?
下面是這個登錄傳遞的源碼:
?
代碼 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的登錄驗證窗體的工作方式:把登錄的驗證方法放在主程序里面,因為,不同時期不同的開發(fā)項目,其登錄驗證方式都不一樣,因此獨立出主程序里,采用回調(diào)的方式來實現(xiàn)。由于登錄窗體需要到數(shù)據(jù)庫中去驗證帳號和密碼,因此,我特意把字段輸錯,這里所報的異常不會被主程序捕捉到,為何不會被主程序捕捉到?我猜是因為調(diào)用這個驗證方法是一個DLL,而DLL畢竟不是主程序,因此,其錯誤消息是不會被主程序所捕捉到的,就算開始的時候把a(bǔ)pplication傳到了dll里面去也一樣捕捉不到(如果能捕捉到的,請把方法告訴我,我找了很久都沒找到相關(guān)的資料),在網(wǎng)上找了個資料,網(wǎng)址是:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3660866
根據(jù)這個提示,我把異常處理的方法也傳進(jìn)去了,這樣,在驗證登錄方法時出錯了,也能調(diào)用主程序中的捕捉異常的方法。
?
原創(chuàng)作品出自努力偷懶,轉(zhuǎn)載請說明文章出處:http://www.cnblogs.com/kfarvid/
轉(zhuǎn)載于:https://www.cnblogs.com/kfarvid/archive/2010/08/06/1794307.html
總結(jié)
以上是生活随笔為你收集整理的Delphi捕捉DLL执行所抛出的异常。的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 方法重载简单小例子
- 下一篇: bzoj 1024 [ SCOI 200