原地址:http://blog.csdn.net/allenky/archive/2008/10/16/3087444.aspx
在改写一个软件的自动更新程序时遇到一个问题
exe与dll在载入的时候是不能覆盖与删除的...
自动更新的时候,如何把用http/ftp下载下来的新版本替换旧版本
第一种是最老土的办法:
假设a.exe要更新自己, down下来为a.exe.upd, 关闭自己,并execute一个第三方程序b.exe,
b.exe 功能就是 将a.exe.upd拷贝替换a.exe,再execute a.exe
优点:用几个简单的api就能搞定,基本上没什么难度...许多软件/游戏的自动更新程序用这种办法
缺点:适应性差,不能用于被别的程序占用文件的改写,只能用于exe文件,而且名称之类相对固定,需要第三方程序
第二种重启计算机大法
一般的安装程序都用此法,象驱动程序,系统软件安装,均提示需要重启电脑生效,
这种方法涉及到一个关键的API ::MoveFileEx 些函数详见MSDN
BOOL MoveFileEx(
LPCTSTR lpExistingFileName,
LPCTSTR lpNewFileName,
DWORD dwFlags
);
它的第三个参数使用
MOVEFILE_DELAY_UNTIL_REBOOT标志与MOVEFILE_REPLACE_EXISTING标志时
将在电脑启动时,自动替换文件...
以下是半伪半真代码...
a.exe 下载新版本a.exe.upd
if succeed(deletefile( a.exe))
movefile(a.exe.upd,a.exe);//如果删除成功,直接替换
else
{
MoveFileEx("'a.exe", "a.exe.upd",MOVEFILE_DELAY_UNTIL_REBOOT|MOVEFILE_REPLACE_EXISTING);
MessageBox("restart computer, yes/no?");
}
优点:适用性强,基本上能处理任何类型和任何情况的文件,非常保险
缺点:要重启计算机
第三种方法,也是我试过很多种后,使用的办法
前面说过exe与dll在载入的时候是不能覆盖与删除的,但是它能被改名
a.exe 下载新版本a.exe.upd
先将a.exe改成a.exe.tmp,
现在a.exe.tmp是不能被删除与覆盖的,
而a.exe这个文件不存在了
将a.exe.upd改名为a.exe
再关闭自己,重新启动a.exe,这时a.exe已经是新版的了
DeleteFile("a.exe.tmp");//以防万一,删除a.exe.tmp
Rename("a.exe","a.exe.tmp");
if SUCCEED(Rename("a.exe.upd","a.exe")){
Execute("a.exe");
CloseSelf();
}
else{
//特殊情况,连a.exe.tmp都被占用了,按第二种方法重启处理吧
}
优点:自己搞定,简单明了
缺点:不能用于被别的程序占用文件的改写,只能用于exe或者dll文件