我只要制作了升级程序,客户只要点击升级即可,而不管系统安装路径是什么!
解决方案 »
- web Service,client连接server一直报错
- 模态窗体关闭问题,大家救救急!
- Dephi7与Interbase数据库开发问题.
- 取相反数
- 如何用钩子实现系统键的记录和回放
- ★★★关于语句速度优化的问题,请高手赐教!★★★
- Delphi中,如何将两个表对比关联的ID,把A表ID=B表ID的A表的X字段值显示在标签Memo1上
- 在画了n遍之后,画布说‘EInvalidOperation,message:Canvas does not allow drawing’
- 各位有没有VBA的相关资料或者电子书籍,或者Delphi操作WORD的相关资料,急用。。。在线等候。。。
- 用dephi+ado控件开发的access 2000应用程序在发布时需要带哪些包?
- 32bitDelphi深度历险被黑了?
- 如何创建“变量是按钮”的过程
软件每次运行都会登陆上述FTP检查最新的版本,如果有新的就会按照上面写的下载地址去下载
然后提示用户安装
实现原理
PiUpdate模块的基本设计思想是将要更新的文件放在文件服务器上,工作站上的程序启动时调用PiUpdate, 对比服务器上的文件和本地的文件,如发现有新文件,则更新本地的对应文件。
首先,考虑到通用性的要求,将该模块设计成一个Windows标准的动态链接库(DLL),并在DLL中提供一个接口函数供其他程序调用。由于几乎各种开发工具都支持DLL调用机制,这样就保证了模块的通用性。
其次,为了灵活控制具体的更新文件,笔者使用了一个ini文件来提供相关的更新信息。ini文件名在主程序调用DLL接口函数时传入程序。
接口函数的定义形式如下:
function ExecuteUpdate(IniFileName:Pchar):integer; stdcall;
如果更新成功,则返回0,如果出现错误,则返回-1; 当将要更新的文件被运行中的应用程序使用时,接口函数会向主程序返回1。
接口函数的调用形式如下:
Delphi调用:function ExecuteUpdate(inifilename:pchar):integer;stdcall;external ‘PiUpdate.dll’;
PB调用:function integer ExecuteUpdate(ref string name) library“PiUpdate.dll”
考虑到不同编程语言中字符串存储形式不尽相同,函数参数采用了Windows API标准的C语言字符串形式,并且调用形式也采用Windows标准的StdCall形式。
配置ini文件的形式如下:
[程序名称]
filename1=\\Server\Share\filename1
filename2=\\Server\Share\filename2
…
更新方法
本文在更新一般文件时,使用的是CopyFile API。对于正在使用的文件,这个方法就行不通了。开始时,笔者查找了Windows API的有关资料,发现MoveFileEx函数可以在Windows重新启动时更新指定文件,这可以作为一种更新正在使用的文件的方法。但如果只是更新一个小程序,就要用户重新启动,有点小题大做的味道。后来,笔者在网上看到HAPPYZSL的一篇文章,发现其中使用的技巧十分有效。更新过程的思路是:如果发现被更新的文件正在使用,则将源文件复制到本地的一个临时文件,并建立一个del.BAT文件。在程序结束时运行该BAT文件,以完成对这些正在使用的文件的更新。del.BAT文件的内容如下:
@echo off
: loop
del destfile
if exist destfile goto loop
copy tmpfile destfile
del tmpfile
del .\del.bat
由于del.BAT运行后会一直执行,直到成功地删除了目标文件为止,所以主程序在检测到接口函数ExecuteUpdate返回值为1时,要立即退出,以便del.BAT能顺利地执行下去。
程序实现
主程序的实现代码如下:
function ExecuteUpdate(IniFileName: Pchar):integer;
//返回值:0 更新成功;-1 更新出错; 1 要更新的文件正在使用,需要立即退出程序
begin
result: =-1 ;
//获取配置文件名称
FName: =StrPas(IniFileName);
ProgList: =TStringList.Create;
try
//初始化更新配置信息
if InitUpdate(FName) then
begin
UpdateList:=TStringList.Create;
try
//检查需要更新的文件
if CheckNeedUpdate(ProgList,
UpdateList) then
//执行更新操作
result: =DoUpdate(UpdateList)
else
result: =0;
finally
UpdateList.Free;
end;
end;
finally
ProgList.Free;
end;
end;
小 结
如果在建立ini文件时,没有指定文件的目录位置,则默认使用Windows的系统目录,所以在调用接口函数时最好用ini文件的全路径名称。如果不方便给出全路径名称,也可以采用“.\filename.ini”的形式进行调用。
对于文件是否需要更新,程序员可以根据实际情况来编写判断标准。为方便修改,在程序中将其写成函数FileDiff(sFile,dFile: string)的形式,可以加上文件大小、版本号等条件。
为了使更新过程能更加完善,建议将本模块及更新配置文件也放在服务器上相应的共享目录下,并作为待更新的文件加到更新文件列表中。这样一来,如果服务器端的PiUpdate.dll更新了,用户的PiUpdate.dll也会同样得到更新。如果由于程序功能的增加,加入了新的文件,只要将新加的文件放到服务器上,并修改服务器上的更新配置文件,工作站上的程序启动时会先将新的配置文件复制到本地,下次本地程序再启动时就可以更新新加入的文件。