实现局域网中客户端程序的自动分发与更新关于程序开发中C/S和B/S两种模式的讨论网上随处可见,B/S模式以其客户端的零维护等优点已逐渐成为主流的开发模式。随着绿色软件的盛行,很多客户端程序不需要进行安装,因此有些面向局域网应用的项目中,程序员完全可以根据具体应用开发出C/S程序,为了方便客户端程序升级维护,可以结合B/S模式的优点,实现客户端用浏览器自动下载升级客户端程序。笔者曾经用Delphi开发了一个面向局域网的C/S模式的系统,最近因客户业务变化客户端程序需要随时进行更新与维护。如果每一次升级维护都需要管理员到每个部门每台客户机进行重新复制文件,用户显然是难以接受的。因此笔者考虑做一个ActiveX控件嵌入到Html页面文件中,让用户借助浏览器实现客户端程序的自动分发、更新。以下以Delphi开发工具为例,将解决过程及基本代码写出来,所有代码在Delphi7+Window9X、Win2k、WinXP下测试过。一、解决问题的思路及要点InternetExplorer3.0以上版本就支持在网页中嵌入ActiveX控件,用户通过浏览器访问网页时,将网页中的控件下载,并在用户机器上注册,以后就可在用户的浏览器上运行。控件下载一次后就驻留在用户本地机器上,下次再访问相同的网页时,如果ActiveX控件的版本不变,不再下载该控件,而是直接运行用户本地的控件。因此我们可以在Delphi中创建一个ActiveX控件,以实现自动下载客户端程序的功能。在Delphi中实现文件下载的方法很多,比较简便的是直接用idHTTP组件。idHTTP提供了个Get方:Get(AURL:String;ConstAresPonseContent:Tstream),该方法用Tstrem来封装了返回的内容,通过对Tstream的SaveTo方法来保存下载的文件。Get方法必须指定下载文件正确的URL,而服务端的IP是可能改变的。在HTML中,利用脚本技术JavaScript可以获取当前网页的URL,当访问者用浏览器打开一个网页时,JavaScript将产生一个指向该页面的Document对象,Document的Location属性用于指定当前网页的URL。因此在编写代码时必须将Get方法的AURL参数设定为一个变量,这样可以先获取服务端网页的URL后,再传递给Get方法以便正确下载文件。正确下载客户端程序后,还应该自动执行该程序。在DELPHI使用函数WinExce(lpCmdLine:pAnsichar;uCmdShow:Cardinal)即可执行外部EXE文件。最后还应自动关闭打开的浏览器,可以利用动态数据交换技术DDE实现。Windows的DDE机基于Windows的消息机制,两个应用程序通过相互之间传递DDE消息进行DDE会话,从而完成数据的请求、应答、传输,这两个应用程序分别称为服务器和客户。打开的浏览器可作为服务器,而ActiveX可作为客户,Delphi的组件TDDEClinetConv用于客户程序建立和维护一个DDE会话。在浏览器未降低安全级别时,用户从客户机上访问嵌入了ActiveX的页面,不会弹出下载提示,用户仍然不能下载,因为该控件还没有证书,浏览器直接禁用。为此我们可以从网上下载数字签名工具建一个测试证书并对该控件进行数字签名。关于数字签名可以参见资料。二、操作过程说明1.在Delphi中创建ActiveForm:在Delphi7中,点击【File】→【New】→【Other…】→【ActiveX】→【ActiveForm】什么是ActiveForm?ActiveForm也是ActiveX控件。不同的是,一般的ActiveX控件是单一的控件,只能从一个VCL控件转换而来,而ActiveForm可以把一个或多个VCL控件转换为一个复合的ActiveX控件。在接下来的ActiveFormWinzard对话框中NewAcitveXName项目中输入要创建的控件名如DownClient,其它默认。点击“确定”按钮后,Delphi中就创建了ActiveForm。从【SyStem】组件面板中拖入一个DdeClientConv组件,以实现关闭打开的浏览器。从【IndyClients】组件面板中拖入一个idHTTP控件,以实现文件下载。2.为ActiveForm添加一个方法点击菜单栏中【View】→【TypeLibrary】给当前控件添加一个方法,以接收需要下载文件的URL。在打开的类型库编辑窗口中点击“NewMethod”按钮,取名为GetDownUrl。在右边窗口中选中“Parameters”选项页,在此定义一个参数。参数名DownUrl,类型定义为BSTR。定义好后,还必须在该窗口中工具栏上点击“RegisterTypeLibrary”按钮以注册该方法。系统会弹击一个注册成功的消息框,如下图。点击“OK”按钮,关闭类型库编辑窗口,在unitDownClientImpl1单元中,可以看到系统自动添加的过程GetDownUrl(constDownUrl:WideString)。3.添加代码procedureTDownClient.GetDownUrl(constDownUrl:WideString);varsource,dest:string;DDE:TDDEClientConv;WinDir:Pchar;MyStream;TMemoryStream;begintry//获取系统目录GetMem(WinDir,256);getwindowsdirectory(WinDir,128);IFFileExists(Windir+'\Client.exe')thenDeleteFIle(Windir+'\Client.exe');//删除客户端文件MyStream:=TMemoryStream.Create;//下载客户端文件Client.exeSource:=DownUrl+'Client.exe';Dest:=Windir+'\Client.exe';IdHTTP1.Get(Source,MyStream);MyStream.SaveToFile(Dest);MyStream.Free;//释放//执行客户端EXE文件winexec(pchar(Windir+'\Client.exe'),SW_SHOWNORMAL);Finally//关闭当前打开的IE浏览器DDE:=TDDEClientConv.Create(self);//创建DDE客户端IfDDE.etLink('iexplore',')then//建立DDE连接DDE.RequestData(');//关闭IEDDE.Free;end;end;4.编译ActiveForm设计好ActiveForm后,还需要正确设置相关的选项:使用【Project】→【WebDeploymentOptions】菜单命令打开对话框,指定输出路径。TargetDir:用于指定要发布的ActiveForm在Web服务器上的路径。如:C:\inetpub\:用于指定要发布的ActiveForm在Web服务器上的URL。如:用于指定生成的样本HTML文件的路径,该文件包括对ActiveForm的引用,做测试用。使用【Project】→【WebDeploy】来编译该ActiveForm。Delphi在指定的目录下生成一个Web页和一个ActiveX控件DownClientProj1.ocx。下面是产生的样本Web页:HTMLH1Delphi7ActiveXTestPage/H1pYoushouldseeyourDelphi7formsorcontrolsembeddedintheformbelow.HRcenterPOBJECTclassid=clsid:BA667154-2695-4319-868A-14216279740Ecodebase==1,0,0,0width=350height=250align=centerhspace=0vspace=0/OBJECT/HTML5.修改Web页面的内容在样本Web文件中,用/OBJECT标记了ActiveX的属性。在本文前面分析到,可以用HTML的DOCUMENT对象的LOCATON属性获取当前页面的URL以传递给ActiveX的GetDownUrl(constDownUrl:WideString)方法,以便正确下载客户端文件,因此,应当修改WEB文件内容如下:OBJECTname=zxt//给ActiveX赋一个名称属性classid=clsid:BA667154-2695-4319-868A-14216279740Ecodebase==1,0,0,0width=350height=250align=centerhspace=0vspace=0/OBJECTscriptlanguage=javascriptzxt.GetDownUrl(document.location)/script6ActiveX控件数字签名证书由下面过程产生:(1)产生名为zhangxt(自己命名)的证书与私钥文件,私钥为zhangxtmakecert-nCN=公司名称-svzhangxt.pvkzhangxt.cer(2)由证书生成spccert2spczhangxt.cerzhangxt.spc(3)对DownClientProj1.ocx控件进行签名:SIGNCODEDownClientProj1.ocx-spczhangxt.spc-vzhangxt.pvk当用户在客户端用浏览器访问服务端的网页时,浏览器会弹出下载提示如下图,如果用户选择“是”,则网页中的ActiveX会下载到用户端客户机,ActiveX会自动下载客户端程序并在本地机执行,自动关闭打开的浏览器,不再需要〖LL〗管理人员到每个部门每台客户机上重新复制文件,实现了客户端程序的自动分发。客户端程序升级后只要将升级后的程序放在服务端覆盖原来程序即可,这样就实现了程序的自动更新。限于篇幅,本文旨在介绍解决问题的思路及要点,并列出简要代码,其实在实际应用时还需加上一些功能,如客户端程序不只一个EXE文件还有DLL文件,配置文件时可以遍历文件夹逐个进行下载,还可以根据用户权限实现下载不同的文件列表等,读者应根据自己的实际应用进行完善。当然,如果客户端程序不是绿色软件,需要用户人工进行安装操作时,本文所介绍的方法显然是达不到客户端零维护这个要求的。另外,用本文所介绍的方法进行程序自动下载时,建议在服务端进行IIS设置时,“执行许可(P)”项目设置为“无”,而不要设置成为“脚本和可执行程序”,因为ActiveX会把exe文件认为可执行程序立即进行执行,这样就不能正确下载了。