[转]在WinForm应用程序中实现自动升级

本文介绍了一种自动升级组件的设计与实现,该组件支持多文件更新,可在应用程序中轻松集成。组件通过对比服务器配置文件与本地配置文件来判断是否需要进行升级。

这是本人第一次写比较复杂的文章,表达不清之处,请各位见谅。好,闲话少说,入正题。

最近单位开发一个项目,其中需要用到自动升级功能。因为自动升级是一个比较常用的功能,可能会在很多程序中用到,于是,我就想写一个自动升级的组件,在应用程序中,只需要引用这个自动升级组件,并添加少量代码,即可实现自动升级功能。因为我们的程序中可能包含多个exe或者dll文件,所以要支持多文件的更新。

首先,要确定程序应该去哪里下载需要升级的文件。我选择了到指定的网站上去下载,这样比较简单,也通用一些。在这个网站上,需要放置一个当前描述最新文件列表的文件,我们估且叫它服务器配置文件。这个文件保存了当前最新文件的版本号(lastver),大小(size),下载地址(url),本地文件的保存路径(path),还有当更新了这个文件后,程序是否需要重新启动(needRestart)。这个文件大致如下:
updateservice.xml

<?xmlversion="1.0"encoding="utf-8"?>
<updateFiles>
<filepath="AutoUpdater.dll"url="http://update.iyond.com/CompanyClientApplication/AutoUpdater.zip"lastver="1.0.0.0"size="28672"needRestart="true"/>
<filepath="CompanyClient.exe"url="http://update.iyond.com/CompanyClientApplication/CompanyClient.zip"lastver="1.1.0.0"size="888832"needRestart="true"/>
<filepath="HappyFenClient.dll"url="http://update.iyond.com/CompanyClientApplication/HappyFenClient.zip"lastver="1.0.0.0"size="24576"needRestart="true"/>
<filepath="NetworkProvider.dll"url="http://update.iyond.com/CompanyClientApplication/NetworkProvider.zip"lastver="1.0.0.0"size="32768"needRestart="true"/>
<filepath="Utility.dll"url="http://update.iyond.com/CompanyClientApplication/Utility.zip"lastver="1.0.0.0"size="20480"needRestart="true"/>
<filepath="Wizard.dll"url="http://update.iyond.com/CompanyClientApplication/Wizard.zip"lastver="1.0.0.0"size="24576"needRestart="true"/>
</updateFiles>

同时,客户端也保存了一个需要升级的本地文件的列表,形式和服务器配置文件差不多,我们叫它本地配置文件。其中,<Enable>节点表示是否启用自动升级功能,<ServerUrl>表示服务器配置文件的地址。
update.config

<?xmlversion="1.0"encoding="utf-8"?>
<Configxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Enabled>true</Enabled>
<ServerUrl>http://update.iyond.com/updateservice.xml</ServerUrl>
<UpdateFileList>
<LocalFilepath="AutoUpdater.dll"lastver="1.0.0.0"size="28672"/>
<LocalFilepath="CompanyClient.exe"lastver="1.1.0.0"size="888832"/>
<LocalFilepath="HappyFenClient.dll"lastver="1.0.0.0"size="24576"/>
<LocalFilepath="NetworkProvider.dll"lastver="1.0.0.0"size="32768"/>
<LocalFilepath="Utility.dll"lastver="1.0.0.0"size="20480"/>
<LocalFilepath="Wizard.dll"lastver="1.0.0.0"size="24576"/>
</UpdateFileList>
</Config>

使用自动各级组件的程序在启动时,会去检查这个配置文件。如果发现有配置文件中的文件版本和本地配置文件中描述的文件版本不一致,则提示用户下载。同时,如果本地配置文件中某些文件在服务器配置文件的文件列表中不存在,则说明这个文件已经不需要了,需要删除。最后,当升级完成后,会更新本地配置文件。

我们先来看一下如何使用这个组件。
在程序的Program.cs的Main函数中:

[STAThread]
staticvoidMain()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(
false);

AutoUpdaterau
=newAutoUpdater();
try
{
au.Update();
}
catch(WebExceptionexp)
{
MessageBox.Show(String.Format(
"无法找到指定资源\n\n{0}",exp.Message),"自动升级",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
catch(XmlExceptionexp)
{
MessageBox.Show(String.Format(
"下载的升级文件有错误\n\n{0}",exp.Message),"自动升级",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
catch(NotSupportedExceptionexp)
{
MessageBox.Show(String.Format(
"升级地址配置错误\n\n{0}",exp.Message),"自动升级",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
catch(ArgumentExceptionexp)
{
MessageBox.Show(String.Format(
"下载的升级文件有错误\n\n{0}",exp.Message),"自动升级",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
catch(Exceptionexp)
{
MessageBox.Show(String.Format(
"升级过程中发生错误\n\n{0}",exp.Message),"自动升级",MessageBoxButtons.OK,MessageBoxIcon.Error);
}

Application.Run(
newMainUI());
}

如上所示,只需要简单的几行代码,就可以实现自动升级功能了。

软件运行截图:






下面,我们来详细说一下这个自动升级组件的实现。
先看一下类图:

AutoUpdater:自动升级的管理类,负责整体的自动升级功能的实现。
Config:配置类,负责管理本地配置文件。
DownloadConfirm:一个对话框,向用户显示需要升级的文件的列表,并允许用户选择是否马上升级。
DownloadFileInfo:要下载的文件的信息
DownloadProgress:一个对话框,显示下载进度。
DownloadProgress.ExitCallBack,
DownloadProgress.SetProcessBarCallBack,
DownloadProgress.ShowCurrentDownloadFileNameCallBack:由于.NET2.0不允许在一个线程中访问另一个线程的对象,所以需要通过委托来实现。
LocalFile:表示本地配置文件中的一个文件
RemoteFile:表示服务器配置文件中的一个文件。
UpdateFileList:一个集合,从List<LocalFile>继承

我们先整体看一下AutoUpdater.cs:
AutoUpdater.cs
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->publicclassAutoUpdater
{
conststringFILENAME="update.config";
privateConfigconfig=null;
privateboolbNeedRestart=false;

publicAutoUpdater()
{
config
=Config.LoadConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,FILENAME));
}

/**////<summary>
///检查新版本
///</summary>
///<exceptioncref="System.Net.WebException">无法找到指定资源</exception>
///<exceptioncref="System.NotSupportException">升级地址配置错误</exception>
///<exceptioncref="System.Xml.XmlException">下载的升级文件有错误</exception>
///<exceptioncref="System.ArgumentException">下载的升级文件有错误</exception>
///<exceptioncref="System.Excpetion">未知错误</exception>
///<returns></returns>
publicvoidUpdate()
{
if(!config.Enabled)
return;
/**//*
*请求Web服务器,得到当前最新版本的文件列表,格式同本地的FileList.xml。
*与本地的FileList.xml比较,找到不同版本的文件
*生成一个更新文件列表,开始DownloadProgress
*<UpdateFile>
*<Filepath=""url=""lastver=""size=""></File>
*</UpdateFile>
*path为相对于应用程序根目录的相对目录位置,包括文件名
*/
WebClientclient
=newWebClient();
stringstrXml=client.DownloadString(config.ServerUrl);

Dictionary
<string,RemoteFile>listRemotFile=ParseRemoteXml(strXml);

List
<DownloadFileInfo>downloadList=newList<DownloadFileInfo>();

//某些文件不再需要了,删除
List<LocalFile>preDeleteFile=newList<LocalFile>();

foreach(LocalFilefileinconfig.UpdateFileList)
{
if(listRemotFile.ContainsKey(file.Path))
{
RemoteFilerf
=listRemotFile[file.Path];
if(rf.LastVer!=file.LastVer)
{
downloadList.Add(
newDownloadFileInfo(rf.Url,file.Path,rf.LastVer,rf.Size));
file.LastVer
=rf.LastVer;
file.Size
=rf.Size;

if(rf.NeedRestart)
bNeedRestart
=true;
}


listRemotFile.Remove(file.Path);
}

else
{
preDeleteFile.Add(file);
}

}


foreach(RemoteFilefileinlistRemotFile.Values)
{
downloadList.Add(
newDownloadFileInfo(file.Url,file.Path,file.LastVer,file.Size));
config.UpdateFileList.Add(
newLocalFile(file.Path,file.LastVer,file.Size));

if(file.NeedRestart)
bNeedRestart
=true;
}


if(downloadList.Count>0)
{
DownloadConfirmdc
=newDownloadConfirm(downloadList);

if(this.OnShow!=null)
this.OnShow();

if(DialogResult.OK==dc.ShowDialog())
{
foreach(LocalFilefileinpreDeleteFile)
{
stringfilePath=Path.Combine(AppDomain.CurrentDomain.BaseDirectory,file.Path);
if(File.Exists(filePath))
File.Delete(filePath);

config.UpdateFileList.Remove(file);
}


StartDownload(downloadList);
}

}

}


privatevoidStartDownload(List<DownloadFileInfo>downloadList)
{
DownloadProgressdp
=newDownloadProgress(downloadList);
if(dp.ShowDialog()==DialogResult.OK)
{
//更新成功
config.SaveConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,FILENAME));

if(bNeedRestart)
{
MessageBox.Show(
"程序需要重新启动才能应用更新,请点击确定重新启动程序。","自动更新",MessageBoxButtons.OK,MessageBoxIcon.Information);
Process.Start(Application.ExecutablePath);
Environment.Exit(
0);
}

}

}


privateDictionary<string,RemoteFile>ParseRemoteXml(stringxml)
{
XmlDocumentdocument
=newXmlDocument();
document.LoadXml(xml);

Dictionary
<string,RemoteFile>list=newDictionary<string,RemoteFile>();
foreach(XmlNodenodeindocument.DocumentElement.ChildNodes)
{
list.Add(node.Attributes[
"path"].Value,newRemoteFile(node));
}


returnlist;
}

publiceventShowHandlerOnShow;
}


在构造函数中,我们先要加载配置文件:
publicAutoUpdater()
{
config
=Config.LoadConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,FILENAME));
}

最主要的就是Update()这个函数了。当程序调用au.Update时,首先检查当前是否开户了自动更新:
if(!config.Enabled)
return;

如果启用了自动更新,就需要去下载服务器配置文件了:
WebClientclient=newWebClient();
stringstrXml=client.DownloadString(config.ServerUrl);

然后,解析服务器配置文件到一个Dictionary中:
Dictionary<string,RemoteFile>listRemotFile=ParseRemoteXml(strXml);

接下来比较服务器配置文件和本地配置文件,找出需要下载的文件和本地需要删除的文件:
List<DownloadFileInfo>downloadList=newList<DownloadFileInfo>();
//某些文件不再需要了,删除
List<LocalFile>preDeleteFile=newList<LocalFile>();

foreach(LocalFilefileinconfig.UpdateFileList)
{
if(listRemotFile.ContainsKey(file.Path))
{
RemoteFilerf
=listRemotFile[file.Path];
if(rf.LastVer!=file.LastVer)
{
downloadList.Add(
newDownloadFileInfo(rf.Url,file.Path,rf.LastVer,rf.Size));
file.LastVer
=rf.LastVer;
file.Size
=rf.Size;

if(rf.NeedRestart)
bNeedRestart
=true;
}

html>
【无人机】基于改进粒子群算法的无人机路径规划研究[和遗传算法、粒子群算法进行比较](Matlab代码实现)内容概要:本文围绕基于改进粒子群算法的无人机路径规划展开研究,重点探讨了在复杂环境中利用改进粒子群算法(PSO)实现无人机三维路径规划的方法,并将其与遗传算法(GA)、标准粒子群算法等传统优化算法进行对比分析。研究内容涵盖路径规划的多目标优化、避障策略、航路点约束以及算法收敛性和寻优能力的评估,所有实验均通过Matlab代码实现,提供了完整的仿真验证流程。文章还提到了多种智能优化算法在无人机路径规划中的应用比较,突出了改进PSO在收敛速度和全局寻优方面的优势。; 适合人群:具备一定Matlab编程基础和优化算法知识的研究生、科研人员及从事无人机路径规划、智能优化算法研究的相关技术人员。; 使用场景及目标:①用于无人机在复杂地形或动态环境下的三维路径规划仿真研究;②比较不同智能优化算法(如PSO、GA、蚁群算法、RRT等)在路径规划中的性能差异;③为多目标优化问题提供算法选型和改进思路。; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注算法的参数设置、适应度函数设计及路径约束处理方式,同时可参考文中提到的多种算法对比思路,拓展到其他智能优化算法的研究与改进中。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值