用 Delphi 5 编写 ASP 对象

Delphi 5 一项重要的新增功能便是可以编写供 ASP 使用的 ActiveX 组件, 而 ASP 也正是因为与 ActiveX 组件的结合而成为一项极有竞争力的服务端脚本技术,包括 ASP 用于访问 数据库的 ADO 组件也是,此外还有一些其它的 ASP 组件如: AdRotator、 Counter 等也都是。很多人 因为 PHP 版本更新快,新功能不断增加,较之 ASP 几年更新一次更适合于 Internet 上日新月异的变化 并更有优势,我在很多 PHP 的书中都看到这种说法,虽然这是事实,但他们忽略了 ASP 优秀的可扩展性, ActiveX/COM 已经成为 Windows 平台下最标准的扩展规范,你可以通过为 ASP 编写 ActiveX 组件来增加 几乎是任何功能,而 PHP 就没有如此方便的扩展功能,当然 PHP 也有它的优势,首先便是功能齐全,几乎 所有在 Internet 应用中所要用到的功能, PHP 均有提供,从 FTP 到 Socket 一应俱全。我不是要 在这里说明 ASP 和 PHP 的优劣,我只是想对某些作者的偏见发表一些自已的看法,当然这种错误我也在犯, 比如我一向就很讨厌 VB ,对此我也从不否认,应该说明的是,理论上 VB 也可以写出任何程序。


扯远了,回到 Active Server Object 上来,虽然这是 Delphi 5 的一项 重要的新增功能,但是"Delphi 5 Developer's Guide"对此的说明只有区区 5 页 (见 Chapter 49 Creating an Active Server Page ),我仔细研究了这 5 页的内容,用 Delphi 5 实现 这一功能可算是相当简单,这 5 页的内容也基本上将 Active Server Object 的方方面面都说到了,但由于 没有实例以助理解,并且在许多重要问题上常常是一句带过,没有更详细的说明,实际编程中会碰到不少困难, 当然,如果你熟悉用 Delphi 编写 ActiveX 的技术则另当别论。正好我有一朋友要一个用于发送 E-mail 的 ASP 组件,下面我就结合这个程序的编写来说明一下用 Delphi 5 编写 Active Server Object 的方法, 为简单起见,程序使用了 NetMaster 的 TNMSMTP 控件,这虽有违我们不用无源程序控件的说法,但不得已 而为之,如果不用就太麻烦了。另,如果你是一位用 ActiveX 的高手那我就是班门弄斧了。

1. 建立工程:建议新建一个 ActiveX Lib ,这是一个 DLL ,或称之为 in-process 组件,最好不要建立 Application ,即 EXE ,或叫 out-of-process 组件,虽然理论上可以, 但实际中会遇到许多问题,这在"Delphi 5 DG"中也有说明,当然用 DLL 也会有一些麻烦,后面会谈到这一点; 建立工程完成后给工程起个名如 AxSrvObj 并保存;

2. 新建 Active Server Object :对于将用于 IIS4/PWS4 的 ASP 组件,建议除 输入对象名 CoClassName 外,其它均保持不变,即 Instancing 为 Multiple Instance ,Threading Model 为 Apartment , Active Server Type 为 Page-Level event menthods(OnStartPage/OnEndPage)(注:若 用于 IIS 5 此项可以为 Object Context ), Options 选中将产生一个 ASP 页的模版,可作测试用;现设 对象名为:SendMail ,单元文件保存为 SendMailImpl.pas ,ASP 页保存为 test.asp ;

3. 按 Ctrl-F9 编译,再选 Run-Register ActiveX Server 注册:虽然此程序还 未写,但建议先编译注册;

4. 定义接口:在 Type Library Editor 中的 ISendMail 下增加 Connect、 Disconnect 和 SendMail 三个方法,及 FromAddress 、 FromName 和 ReplyTo 三个只写属性,类型均为 BSTR ; Connect 有三个参数: aHost:BSTR, aPort:long, aUserID:BSTR (参数名前的 "a" 表示 argument"参数" ,这是我个人的习惯),分别表示 SMTP 主机,SMTP 端口(默认为 25)和 SMTP 用户名 (仅用于需要授权的 SMTP 服务器,通常为空即可); SendMail 有六个参数: aToAddress:BSTR, aSubject:BSTR, aBody:BSTR, aAttachments:BSTR, aToCC:BSTR, aToBCC:BSTR,分别表示收件人信箱, 主题,信件内容,附件文件名,抄送,暗送,它们的用法见后面 test.asp 中的说明;

5. 实现接口:定义完接口后,点 Type Library Editor 中的 Refresh 刷新, 在 SendMailImpl.pas 单元中产生相应的接口定义,在各定义中输入下列代码:

//  在 TSendMail 的定义中加入
private
smtp : TNMSMTP;

// 加在 OnEndPage 的 inherited 一句前
smtp.Abort; // 中止未完的 SMTP 操作
smtp.Free; // 删除 SMTP 对象

// 加在 OnStartPage 的 inherited 一句后
smtp := TNMSMTP.Create( Nil ); // 创建 SMTP 对象

// Connect 方法
With smtp Do
Begin
Host := aHost;
Port := aPort;
UserID := aUserID;
Connect; // 连接到 SMTP SERVER
End;

// Disconnect 方法
smtp.Disconnect; // 断开 SMTP 连接

// SendMail 方法
With smtp.PostMessage Do
Begin // 设置邮件内容
ToAddress.CommaText := aToAddress;
Subject := aSubject;
Body.Text := aBody;
Attachments.CommaText := aAttachments;
ToCarbonCopy.CommaText := aToCC;
ToBlindCarbonCopy.CommaText := aToBCC;
End;
smtp.Charset := 'gb2312'; // 设置语言,这是一个未公开的属性,在帮助中是找不到的,
// 这就是我们为什么尽可能不用没有源程序的控件的原因之一
smtp.SendMail; // 发送邮件

// Set_FromAddress 方法,设置 FromAddress 属性
smtp.PostMessage.FromAddress := Value;

// Set_FromName 方法,设置 FromName 属性
smtp.PostMessage.FromName := Value;

// Set_ReplyTo 方法,设置 ReplyTo 属性
smtp.PostMessage.ReplyTo := Value;

程序到这就算基本上写完了,怎么样,够简单吧;

6. 使用:将 AxSrvObj.dll 所在的目录映射为虚拟目录,并设为可执行权限; 或将文件复制到其它有执行权限的虚拟路径中,如 C:\InetPub\Scripts\ ,并用 RegSvr32/TRegSvr 手工 重新注册组件。具体用法见下面的 test.asp 代码,用的是本地测试用的一个 Mail Server :

<%@LANGUAGE=VBScript%>
<HTML>
<BODY>
<TITLE> Testing Delphi ASP </TITLE>
<CENTER>
<H3> You should see the results of your Delphi Active Server method below </H3>
</CENTER>
<HR>
<%
Set SendMail = Server.CreateObject( "AxSrvObj.SendMail" )
SendMail.Connect "localhost", 25, ""
SendMail.FromAddress = "test@localhost"
SendMail.FromName = "Test"
SendMail.ReplyTo = "test@localhost"
SendMail.SendMail "raptor@localhost", "中文", "中文测试", "test.zip", "", ""
SendMail.Disconnect ' 理论上这两句可以不加,但最好还是加上,保险一些
Set SendMail = Nothing
%>
</BODY>
</HTML>

对这个 ASP 的说明:

SendMail 组件的方法:

1. Connect( string aHost, int aPort, string aUserID );

连接到 SMTP Server , aHost 主机名或地址, aPort 端口号,默认为 25 ,aUserID 仅用于要授权的 SMTP Server。

2.Disconnect;

断开连接。

3.SendMail( string aToAddress, aSubject, aBody, aAttachments, aToCC, aToBCC );

发送。 aToAddress 收件人地址,可以是用逗号或空格分开的多个收件人,aSubject 主题, aBody 内容,以回车分行, aAttachments 附件文件名,以逗号或空格分开的多个文件名,路径在本控件所在的服务器(即 WEB SERVER 中), aToCC 抄送,以逗号或空格分开,aToBCC 暗送,以逗号或空格分开。

SendMail 组件的属性:

1.FromAddress : 发件人地址

2.FromName : 发件人名

3.ReplyTo : 回复地址

注意:为简单起见,本组件未作任何错误处理,小心不要连接错误的服务器或端口号等,或者你也可以自已加入。


当然,在最顺利的情况下,仿照上述步骤即可成功建立一个 Active Server Object , 谁也都希望能如此,但实际上往往会碰上各种问题,调试是一道必不可少的工作,那么 ASO 如何调试?关于这一点, 我建议你去看一看 C.Calvert 的书那里有关于调试 ActiveX 的一些说明 (我看的是那本 BCB 3 的书,不过书中这部分关于 ActiveX 的内容好像不是 C.Calvert 写的);另外,因为这也是一种 DLL ,可以按调试 DLL 的方法来调试,这种方法可能会比 C.Calvert 书中所说的几种方法好用一些,即在 Run-Parameters... 中 设置 Host Application 为 IIS/PWS ,并设置相应参数如下:

IIS: Host Application="C:\Winnt\System32\inetsrv\inetinfo.exe";
parameters="-e w3svc";

PWS: Host Application="C:\Windows\System\inetsrv\pws.exe";
parameters="-w3svc";
 
(以上内容引自某书,不过后来在试用PWS4.0 时,上述方法不行,曾试过不用 Run-Parameters , 而用 Run-Attach to process... 的方法,即在此对话框中选中 INETINFO.EXE ,但问题更多, 最后试着改用:

PWS4.0: Host Application="C:\Windows\System\inetsrv\inetinfo.exe";
parameters="-e w3svc";

,调试结束后用 Run|Program Reset 退出即可) 最后在程序中放上断点后运行即可,写过 ISAPI 的人就知道,这是调试 ISAPI 的方法。另外一个要注意的是:因为 DLL 是 随宿主程序的终止而终止的,所以一旦用 ASP 访问过一个 ActiveX 组件后,它就处于运行中,不可修改,这是用 DLL 的麻烦 之处;解决的办法是:对 IIS 可在 Windows NT 中的“控制面板”上选“服务”,在其中停止“IIS Admin Service”同时 “World Wide Web Publishing Service”也将停止,在“任务管理器”中可以看到“inetinfo.exe”进程终止,它就是 IIS 的 ActiveX/ISAPI 的宿主程序,然后重新启动“World Wide Web Publishing Service”同时“IIS Admin Service”也将启动, 这时就可以修改 ActiveX 的 DLL 了,但下一次运行过此 DLL 后还要重复上述操作,有点麻烦吧;对 PWS 则需要一个 Microsoft Visual Studio 中的工具:“Process Viewer 95 ”,此工具在 VC 中有配,运行此程序,在进程列表中找到“inetinfo.exe”,并将其“Kill”掉, 然后重新运行 PWS 即可。


麻烦。

直接写个smtp server。

老是要用别人的smtp。

万维网 at 2005-12-14T20:10:00+08:00