第一种方法:利用Unit的Initalization与Finalization这两个小节
可以在Unit的这两个小节中安排Unit的进入和退出,但是Program与Library并没有这两个部分,所以只能写在Unit中。
第二种方法:利用ExitProc变量释放资源
在Library的begin..end.中间是可以写代码的,在这里可以放置DLL初始化代码。如果想要做善后工作,则可以利用ExitProc变量。
1、 把ExitProc默认的善后过程地址保存下来。
2、 然后把自定义的过程的地址赋给它,这样DLL退出时就会执行我们制定的程序。
3、 在自定义的过程的最后,把ExitProc恢复原来的默认值,以便DLL能够继续完成原来默认的善后工作。
示例代码:
library ExeToDLLProject;
uses
SysUtils,
Classes,
Forms,
Controls,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
Var // 定义全局变量
PExitProc: Pointer;
Form1: TForm1;
// 实现初始化函数
function ShowForm: TModalResult; stdcall;
begin
Form1 := TForm1.Create(nil);
Result := Form1.ShowModal;
end;
// 释放初始化资料
procedure FreeForm; stdcall;
begin
FreeAndNil(Form1);
end;
exports
ShowForm; //定义出口函数
begin
ShowForm; // 初始化工作
PExitProc := ExitProc; // 保存默认的善后过程地址(保护现场)
ExitProc := @FreeForm; // 把自定义的过程的地址赋给它,然后立即执行
ExitProc := PExitProc; // 恢复原来的默认处理函数,以便DLL能够继续完成原来默认的善后工作
end.
在DLL 工程中,直接点击【Run】,会显示Form1,通过这中方法,也可以对DLL的过程进行调试。
第三种方法:利用DllProc变量
和ExitProc一样,DllProc也是一个在System单元中预定义的变量。它的使用方法与ExitProc有区别,它对自定义处理函数有格式的限制,它会根据传入的参数(Reason)的值分别作出相应的处理。另外必须必须引用Windows单元文件(uses windows)。
1、先写一个具有以下格式的程序: procedure MyDllHandler (Reason: integer);
2、并在library的begin..end.之间, 将这个DLLHandler程序的执行地址赋给DLLProc中,
示例代码:
library ExeToDLLProject;
uses
SysUtils,
Classes,
Forms,
Controls,
windows,
Unit1 in 'Unit1.pas' {Form1},
{$R *.res}
Var // 定义全局变量
PExitProc: Pointer;
Form1: TForm1;
// 实现初始化函数
function ShowForm: TModalResult; stdcall;
begin
Form1 := TForm1.Create(nil);
Result := Form1.ShowModal;
end;
// 释放初始化资料
procedure FreeForm; stdcall;
begin
FreeAndNil(Form1);
end;
Procedure MyDllHandler(Reason: Integer);
begin
case Reason of
DLL_Process_Attach: // 整个DLL的初始化代码
ShowForm;
DLL_Process_Detach: // 整个DLL的善后处理程序
FreeForm;
DLL_Thread_Attach:; // 当主叫端开始一个Thread时
DLL_Thread_Detach:; // 当主叫端终止一个Thread时
end;
end;
exports
ShowForm; //定义出口函数
begin
DllProc := @MyDllHandler;
MyDllHandler(DLL_Process_Attach); // 初始化
MyDllHandler(DLL_Process_Detach); // 释放
end.
由上例可以知道,当DLL支援多进程(Thread)的处理时, DllProc非常适合使用。