fileUrl="http:
//172.0.0.1/UCCompanion/UCCompanionSetup(0922).zip<">
xxmlns="
版本文件主要比较服务端Version.xml文件和客户端Version.xml文件中Version(版本号)是否一致,如果服务端Version属性
大于客户端的Version属性,则通过服务端的fileUrl属性获取新版本的下载地址。
供更新程序使用。
2)删除原有更新包
所有客户端更新文件均下载到C:
\DocumentsandSettings\当前用户名\LocalSettings\Temp文件夹内,当客户端运行后首先判
断是否有新更新包需要下载,如果没有则判断该临时文件夹内是否有旧有安装文件,如果存在,则删除旧有安装文件。
privatevoidRemoveOldSetupFile()
{
try
{
stringtemp=System.Environment.GetEnvironmentVariable("TEMP");
stringfolder=newDirectoryInfo(temp).FullName;
if(File.Exists(folder+@"\"+setupName+".exe"))
{
File.Delete(folder+@"\"+setupName+".exe");
}
if(File.Exists(folder+@"\"+setupName+".msi"))
{
File.Delete(folder+@"\"+setupName+".msi");
}
}
catch{}
}
备注:
关于获取系统特殊文件夹的方法见博客
3)启动下载程序
下载程序和客户端程序是相互独立的,可以通过客户端开启新线程启动下载程序。
下载程序在文件下载结束后可以关掉客户端程序,
并开启新线程启动安装程序进行安装。
privatevoidUpdate()
{
if(ShouldUpdate(query.Version,this.version))
{
MessageBox.Show("请更新客户端文件到版本["+query.Version+"]","更新提示",MessageBoxButtons.OK,
MessageBoxIcon.Asterisk);
System.Diagnostics.Process.Start(Application.StartupPath+@"\AutoUpdater.exe",query.FileUrl);
}
else{RemoveOldSetupFile();}
}
privateboolShouldUpdate(stringserverVersion,stringlocalVersion)
{
if(!
string.IsNullOrEmpty(serverVersion)&&!
string.IsNullOrEmpty(localVersion))
{
returnserverVersion.CompareTo(localVersion)>0;
}
returntrue;
}
调用AutoUpdater.exe文件时需要传入文件下载地址。
System.Diagnostics.Process.Start(Application.StartupPath+@"\AutoUpdater.exe",query.FileUrl);
4)下载程序代码
下载程序界面
usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Text;
usingSystem.Windows.Forms;
usingSystem.Net;
usingSystem.IO;
usingSystem.Threading;
usingSystem.Diagnostics;
namespaceAutoUpdater
{
publicpartialclassMainForm:
Form
{
privateWebClientclient;
privatestringURl;
privatestringfileName;
privatestringpath;
privateconststringapplicationFile="Setup";
publicMainForm(stringurl)
{
InitializeComponent();
this.URl=url;
client=newWebClient();
client.DownloadProgressChanged+=newDownloadProgressChangedEventHandler(client_DownloadProgressChanged);
client.DownloadFileCompleted+=newAsyncCompletedEventHandler(client_DownloadFileCompleted);
client.Proxy=WebRequest.DefaultWebProxy;
client.Proxy.Credentials=newNetworkCredential();
this.Hide();
//Threadthread=newThread(UpdateFile);
//Thread.Sleep(15000);
//thread.Start();
UpdateFile();
}
publicMainForm()
{
InitializeComponent();
}
///
///下载完成调用
///
///
///
voidclient_DownloadFileCompleted(objectsender,AsyncCompletedEventArgse)
{
label1.Text="文件接收完成";
UnZip();
RunUpdate();
}
///
///下载进度条
///
///
///
voidclient_DownloadProgressChanged(objectsender,DownloadProgressChangedEventArgse)
{
this.progressBar1.Value=e.ProgressPercentage;
}
///
///开始下载
///
privatevoidStartDownload()
{
fileName=URl.Substring(URl.LastIndexOf("/")+1,URl.Length-URl.LastIndexOf("/")-1);
path=GetTempFolder();
try
{
WebRequestmyre=WebRequest.Create(URl);
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message,"Error");
}
try
{
label1.Text="开始下载文件...";
client.DownloadFileAsync(newUri(URl),path+@"\"+fileName);
}
catch(WebExceptionexp)
{
label1.Text=exp.Message;
}
}
///
///解压压缩包,格式必须是*.zip,否则不能解压
///因为是调用Windows内部api进行解压,只能够识别zip压缩包
///必须添加C:
\WINDOWS\system32\shell32.dll的引用
///
privatevoidUnZip()
{
try
{
Shell32.ShellClasssc=newShell32.ShellClass();
Shell32.FolderSrcFolder=sc.NameSpace(this.path+@"\"+this.fileName);
Shell32.FolderDestFolder=sc.NameSpace(this.path);
Shell32.FolderItemsitems=SrcFolder.Items();
DestFolder.CopyHere(items,20);
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message);
}
}
///
///获取下载文件夹地址及解压文件存放地址
///此地址默认为C:
\DocumentsandSettings\当前用户名\LocalSettings\Temp文件夹
///
///
privatestringGetTempFolder()
{
stringfolder=System.Environment.GetEnvironmentVariable("TEMP");
returnnewDirectoryInfo(folder).FullName;
}
///
///开始下载文件
///
privatevoidUpdateFile()
{
this.Hide();
//如果临时文件夹存在setup安装文件,就直接调用安装文件
if(File.Exists(GetTempFolder()+@"\"+applicationFile+".exe")&&File.Exists(GetTempFolder()+
@"\"+applicationFile+".msi"))
{
label1.Text="开始下载文件...";
this.progressBar1.Value=this.progressBar1.Maximum;
label1.Text="文件接收完成";
RunUpdate();
}
//如果临时文件夹不存在setup安装文件,就从网络下载
else
{
RemoveSetupFile();
StartDownload();
}
}
///
///清除旧有已下载的安装文件
///
privatestaticvoidRemoveSetupFile()
{
try
{
stringtemp=System.Environment.GetEnvironmentVariable("TEMP");
stringfolder=newDirectoryInfo(temp).FullName;
if(File.Exists(folder+@"\"+applicationFile+".exe"))
{
File.Delete(folder+@"\"+applicationFile+".exe");
}
if(File.Exists(folder+@"\"+applicationFile+".msi"))
{
File.Delete(folder+@"\"+applicationFile+".msi");
}
}
catch{}
}
///
///下载完毕,开始执行更新程序
///
privatevoidRunUpdate()
{
try
{
foreach(ProcesspinProcess.GetProcesses())
{
if(p.ProcessName.ToLower().StartsWith("uccompanion"))
{
if(MessageBox.Show("UCCompanion正在运行,是否关闭当前程序安装更新?
","安装UCCompanion",
MessageBoxButtons.YesNo,MessageBoxIcon.Question)==DialogResult.Yes)
{
p.Kill();
Process.Start(GetTempFolder()+@"\"+applicationFile+".exe");
}
else
{
MessageBox.Show("UCCompanion下载完成,将在下次启动时提醒更新!
");
}
}
}
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message);
}
finally
{
this.Close();
}
}
///
///重载WindProc判断点击关闭按钮(X)时,隐藏程序界面
///
///
protectedoverridevoidWndProc(refMessagemsg)
{
constintWM_SYSCOMMAND=0x0112;
constintSC_CLOSE=0xF060;
if(msg.Msg==WM_SYSCOMMAND&&((int)msg.WParam==SC_CLOSE))
{
this.Hide();
return;
}
base.WndProc(refmsg);
}
///
///双击图标弹出界面
///
///
///
privatevoidicon_notify_MouseDoubleClick(objectsender,MouseEventArgse)
{
this.Show();
this.WindowState=FormWindowState.Normal;
}
///
///
///
///
///
privatevoidMainForm_SizeChanged(objectsender,EventArgse)
{
if(this.WindowState==FormWindowState.Minimized)
{
this.Hide();
}
}
privatevoidMainForm_Load(objectsender,EventArgse)
{
this.Hide();
}
}
staticclassProgram
{
///
///启动,接收传入网址作为参数
///
///
[STAThread]
staticvoidMain(string[]agr)
{
if(agr.Length==1&&agr[0].StartsWith(@"http:
//"))
{
MainFormform=newMainForm(agr[0]);
Application.Run(form);
}
}
}
}
程序代码
将AutoUpdater项目生成的文件添加到客户端文件中,在客户端的Update()方法里调用updater,实现更新文件的下载。
以上就已经实现了自动更新功能,下面将讨论文件安装包的制作。
二、安装包的制作
1)创建安装项目
2)鼠标右击Setup项目选择>视图,可以看到制作安装包常见的视图有以下几个
最常用的视图有“文件系统”,“用户界面”和“启动条件”。
3)指定安装属性
鼠标左键单击项目名称,记住是左键单击,然后点击属性标签,注意:
不是右击的属性
a.需要注意的是Version属性,每次版本更新时Version值必须后面的版本大于前面的版本。
每次更改Version值时Projectcode会更改一次。
其中你修改安装项目的版本号时,比如从v1.00到1.01,在你再次生成项目的时候,会提示你是否允许修改ProductCode,选择"是",
程序会自动修改ProductCode,选择否将保持相同的ProductCode,即不能自动卸载旧的版本.
b.在以后版本中要确认和以前的版本两个版本有不同的ProductCode和相同的UpgradeCode
c.manufacturer属性指定制造商名称。
d.detectnewerinstalledversion属性选择为true,
e.removepreviousversions选择为true
鼠标左键单击项目名称,此次是右键单击,然后点击属性,弹出属性页,选择“系统必备”。
在打开的系统必备页中,选中如下中的选择项,这个很重要!
!
!
!
!
1!
!
!
!
!
选上以后,在生成的安装文件包中
包含.netframework组件.(这个选项默认是没有选中的)。
4)文件系统视图
文件系统视图左侧根目录树下有3个子节点。
a.应用程序文件夹:
将所有待打包的应用程序的可执行文件和相应的类库和组件拖动到该目录下。
该目录可以创建子
目录,项目安装完毕以后的文件夹结构会和该目录下结构一致。
如图:
然后右击左边的"应用程序文件夹"打开属性对话框,修改文件释放路径,[ProgramFilesFolder][Manufacturer]\[ProductName]。
安装程序默认安装目录会是"c:
\programmfile\制造商名称\安装解决方案名称";
b.用户的“程序”菜单和用户桌面:
用于在开始菜单创建文件快捷方式
在应用程序文件夹中将需要生成的快捷方式的文件添加快捷方式并拖动到用户的“程序”菜单和用户桌面
c.添加文件卸载功能
在添加你的应用程序项目的时候,多添加一个msiexec.exe进去,这个文件在c:
\windows\system32文件夹下。
为其在程序菜单添加一个快捷方式,把他的名字改成"Uninstall.exe",指定Icon快捷方式显示的图标。
然后下面我们
要的做的就是查找这个部署项目的ProductCode了,鼠标左键单击项目名称,记住是左键单击,然后点击属性标签,注意:
不是右击的属性,这个区别很大,这时你就可以看到ProductCode了
然后打开你创建的那个卸载程序的快捷方式的属性对话框,在Aguements属性中输入"/x{ProductCode}"
5)用户界面视图
在“欢迎使用”后,“安装文件夹”前添加“许可协议”对话框。
licensefile选择协议,协议的格式为rtf。
6)启动条件视图
为启动安装程序制定最低framework要求。
7)实现安装、卸载过程中的其他额外的操作。
比如安装结束后启动程序,卸载程序后同时删除网络下载打安装包等功能。
a.新建一个空的项目InstallCompenent,步骤为:
解决方案->右键添加->新建项目->选择"空项目"->
输入名称"InstallCompenent"->确定,完成项目的添加.
b.在InstallCompenent项目中右键->添加->新建项->选择安装程序类->输入名称"Installer",完成installer类的添加.
修改代码为:
usingSystem;
usingSystem.Collections;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Configuration.Install;
usingSystem.Reflection;
usingSystem.IO;
namespaceInstallCompenent
{
[RunInstaller(true)]
publicpartialcl