一、自动更新的实现

让客户端实现自动更新,通常做法是在客户端部署一个单独的自动更新程序。主程序启动后,访问服务端,检查配置文件是
否有更新版本,有更新版本就启动更新程序,由更新负责下载更新版本,并更新客户端程序,流程如下:

当流程进行到红色部分的是后就调用更新程序进行更新。

1)版本判断:

客户端和服务端都部署同一个版本文件,客户端登陆时发送验证给服务端判断版本是否一致。

Version.xml代码

<iq xmlns="http://www.dynastech.com/xmtp" from="*@domcool.local/updater" to="*@domcool.local/updater" type="get"
id="508f3e88-4bb0-4585-a5c6-cc41ef57fef3"><query xmlns="http://www.dynastech.com/xmtp/disco#update" version="20090922" lastUpdateTime="2009-09-22"
fileUrl="http://172.0.0.1/UCCompanion/UCCompanionSetup(0922).zip    <">
x xmlns="http://www.dynastech.com/xmtp/item"></x></query>
</iq>
版本文件主要比较服务端Version.xml文件和客户端Version.xml文件中Version(版本号)是否一致,如果服务端Version属性
大于客户端的Version属性,则通过服务端的fileUrl属性获取新版本的下载地址。供更新程序使用。
 
2)删除原有更新包
所有客户端更新文件均下载到C:\Documents and Settings\当前用户名\Local Settings\Temp 文件夹内,当客户端运行后首先判
断是否有新更新包需要下载,如果没有则判断该临时文件夹内是否有旧有安装文件,如果存在,则删除旧有安装文件。
private void RemoveOldSetupFile(){try{string temp = System.Environment.GetEnvironmentVariable("TEMP");string folder = new DirectoryInfo(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 { }}

备注:关于获取系统特殊文件夹的方法见博客http://www.cnblogs.com/thornfield_he/archive/2009/09/22/1571719.html

3)启动下载程序

下载程序和客户端程序是相互独立的,可以通过客户端开启新线程启动下载程序。下载程序在文件下载结束后可以关掉客户端程序,
并开启新线程启动安装程序进行安装。

private void Update()
{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(); }
}private bool ShouldUpdate(string serverVersion, string localVersion)
{if (!string.IsNullOrEmpty(serverVersion) && !string.IsNullOrEmpty(localVersion)){return serverVersion.CompareTo(localVersion) > 0;}return true;
}
 
调用AutoUpdater.exe文件时需要传入文件下载地址。
System.Diagnostics.Process.Start(Application.StartupPath + @"\AutoUpdater.exe", query.FileUrl);
 
4)下载程序代码
下载程序界面
 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Threading;
using System.Diagnostics;namespace AutoUpdater
{public partial class MainForm : Form{private WebClient client;private string URl;private string fileName;private string path;private const string applicationFile = "Setup";public MainForm(string url){InitializeComponent();this.URl = url;client = new WebClient();client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);client.Proxy = WebRequest.DefaultWebProxy;client.Proxy.Credentials = new NetworkCredential();this.Hide();//Thread thread = new Thread(UpdateFile);//Thread.Sleep(15000);//thread.Start();UpdateFile();}public MainForm(){InitializeComponent();}/// <summary>/// 下载完成调用/// </summary>/// <param name="sender"></param>/// <param name="e"></param>void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e){label1.Text = "文件接收完成";UnZip();RunUpdate();}/// <summary>/// 下载进度条/// </summary>/// <param name="sender"></param>/// <param name="e"></param>void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e){this.progressBar1.Value = e.ProgressPercentage;}/// <summary>/// 开始下载/// </summary>private void StartDownload(){fileName = URl.Substring(URl.LastIndexOf("/") + 1, URl.Length - URl.LastIndexOf("/") - 1);path = GetTempFolder();try{WebRequest myre = WebRequest.Create(URl);}catch (Exception ex){MessageBox.Show(ex.Message, "Error");}try{label1.Text = "开始下载文件...";client.DownloadFileAsync(new Uri(URl), path + @"\" + fileName);}catch (WebException exp){label1.Text = exp.Message;}}/// <summary>/// 解压压缩包,格式必须是*.zip,否则不能解压/// 因为是调用Windows内部api进行解压,只能够识别zip压缩包/// 必须添加C:\WINDOWS\system32\shell32.dll的引用/// </summary>private void UnZip(){try{Shell32.ShellClass sc = new Shell32.ShellClass();Shell32.Folder SrcFolder = sc.NameSpace(this.path + @"\" + this.fileName);Shell32.Folder DestFolder = sc.NameSpace(this.path);Shell32.FolderItems items = SrcFolder.Items();DestFolder.CopyHere(items, 20);}catch (Exception ex){MessageBox.Show(ex.Message);}}/// <summary>/// 获取下载文件夹地址及解压文件存放地址/// 此地址默认为C:\Documents and Settings\当前用户名\Local Settings\Temp 文件夹/// </summary>/// <returns></returns>private string GetTempFolder(){string folder = System.Environment.GetEnvironmentVariable("TEMP");return new DirectoryInfo(folder).FullName;}/// <summary>/// 开始下载文件/// </summary>private void UpdateFile(){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();}}/// <summary>/// 清除旧有已下载的安装文件/// </summary>private static void RemoveSetupFile(){try{string temp = System.Environment.GetEnvironmentVariable("TEMP");string folder = new DirectoryInfo(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 { }}/// <summary>/// 下载完毕,开始执行更新程序/// </summary>private void RunUpdate(){try{foreach (Process p in Process.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 (Exception ex){MessageBox.Show(ex.Message);}finally{this.Close();}}/// <summary>/// 重载WindProc判断点击关闭按钮(X)时,隐藏程序界面/// </summary>/// <param name="msg"></param>protected override void WndProc(ref Message msg){const int WM_SYSCOMMAND = 0x0112;const int SC_CLOSE = 0xF060;if (msg.Msg == WM_SYSCOMMAND && ((int)msg.WParam == SC_CLOSE)){this.Hide();return;}base.WndProc(ref msg);}/// <summary>/// 双击图标弹出界面/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void icon_notify_MouseDoubleClick(object sender, MouseEventArgs e){this.Show();this.WindowState = FormWindowState.Normal;}/// <summary>/// /// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void MainForm_SizeChanged(object sender, EventArgs e){if (this.WindowState == FormWindowState.Minimized){this.Hide();}}private void MainForm_Load(object sender, EventArgs e){this.Hide();}}static class Program{/// <summary>/// 启动,接收传入网址作为参数/// </summary>/// <param name="agr"></param>[STAThread]static void Main(string[] agr){if (agr.Length == 1 && agr[0].StartsWith(@"http://")){MainForm form = new MainForm(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:\programm file\制造商名称\安装解决方案名称";

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类的添加.

修改代码为:

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Reflection;
using System.IO;namespace InstallCompenent
{[RunInstaller(true)]public partial class UccompanionInstaller : Installer{private const string zipPacket = "UCCompanionSetup(0918).zip";/// <summary>   /// 应用程序入口   /// </summary>   public static void Main(){}/// <summary>   /// 构造函数   /// </summary>   public UccompanionInstaller(){InitializeComponent();}/// <summary>   /// 重写安装完成后函数   /// 实现安装完成后自动启动已安装的程序   /// </summary>   /// <param name="savedState"></param>   protected override void OnAfterInstall(IDictionary savedState){base.OnAfterInstall(savedState);Assembly asm = Assembly.GetExecutingAssembly();string path = asm.Location.Remove(asm.Location.LastIndexOf("\\")) + "\\";System.Diagnostics.Process.Start(path + "\\UCCompanion.exe");}/// <summary>   /// 重写安装过程方法   /// </summary>   /// <param name="stateSaver"></param>   public override void Install(IDictionary stateSaver){base.Install(stateSaver);}/// <summary>   /// 重写安装之前方法   /// </summary>   /// <param name="savedState"></param>   protected override void OnBeforeInstall(IDictionary savedState){base.OnBeforeInstall(savedState);}/// <summary>   /// 重写卸载方法   /// 卸载程序后也删除程序的安装包/// </summary>   /// <param name="savedState"></param>   public override void Uninstall(IDictionary savedState){string temp = System.Environment.GetEnvironmentVariable("TEMP");string folder = new DirectoryInfo(temp).FullName;if (File.Exists(folder + @"\setup.exe")){File.Delete(folder + @"\setup.exe");}if (File.Exists(folder + @"\setup.msi")){File.Delete(folder + @"\setup.msi");}if (File.Exists(folder + @"\"+zipPacket)){File.Delete(folder + @"\"+zipPacket);}base.Uninstall(savedState);}/// <summary>   /// 重写回滚方法   /// </summary>   /// <param name="savedState"></param>   public override void Rollback(IDictionary savedState){base.Rollback(savedState);}}
}

c.在安装项目中右键->添加项目输出->选择"项目"->InstallCompenent.完成主输出项目的添加.

d.打开自定义操作编辑器,在安装->右键->添加自定义操作->选择"应用程序文件夹"->选择"主输出来自InstallCompenent",完成添加.

好了,点击“生成解决方案”,即可以生成带有卸载功能的安装程序了。

转自:http://blog.csdn.net/myhuli120/article/details/6927588

转载于:https://www.cnblogs.com/elim/p/3968333.html

c#自动更新+安装程序的制作相关推荐

  1. usb驱动自安装程序的制作

    这两天询问usb驱动安装程序制作的人很多,我有幸做成过一个这样的安装程序.虽然这两天测试也有人回复说还有问题,但我还是对我的安装程序充满信心. 我也曾在本论坛回答过一些朋友的帖子,但回复成功的似乎还没 ...

  2. Mac使用技巧:在 iPhone 或 iPad 上自动更新应用程序

    如何在 iPhone 或 iPad 上自动安装应用程序更新?按照本提示中的步骤操作,以便您可以自动下载和安装应用程序更新. 在 iOS 中自动更新应用程序 您可以在iPhone和iPad上自动安装应用 ...

  3. 星外php7,星外PHP自动配置安装程序

    星外PHP自动配置安装程序是一款小巧的PHP运行环境配置包,适用于32位的windows操作系统,可以方便快捷地编写,运行速度很快,需要的用户快来下载吧. 软件功能 PHP是一种新型的CGI程序编写语 ...

  4. 计算机策略更新失败怎么办,大神教你解决win10系统自动更新安装失败的途径

    许多win10系统用户在工作中经常会遇到win10系统自动更新安装失败的情况,比如近日有用户到本站反映说win10系统自动更新安装失败的问题,但是却不知道要怎么解决win10系统自动更新安装失败,我们 ...

  5. 通过C#中的在线文件自动更新应用程序

    目录 介绍 背景 使用代码 兴趣点 本文介绍如何在不使用ClickOnce的情况下为您的应用程序提供一键更新或自动更新功能. 下载演示项目-586.48 KB 下载源-1.13 MB 下载Readme ...

  6. C# 实现软件自动更新升级程序

    Update.asmx仅提供一个功能,就是检测是否需要更新,在需要更新的时候就返回一个更新地址,通常情况下返回的地址就是Download.ashx,而在某些特殊情况下,也可以修改服务端使之从其他Url ...

  7. Microsoft IExpress:微软自带的安装程序包制作工具

    iexpress是微软为压缩CAB 文件及制作安装程序所开发的小工具,专用于制作各种 CAB 压缩与自解压缩包的工具,其实应该算是MAKECAB 的一个Shell.虽一直藏身于微软的产品中,却从未对它 ...

  8. 百度SEOB2B/论坛/网站自动更新/发布程序

    下载地址: http://www.bytepan.com/yEyJF4huQZZ 使用说明: 双击setup.exe安装程序 使用软件,必须是windows xp以上系统,且安装了.NET Frame ...

  9. 美剧自动更新下载程序(需要迅雷vip会员的离线下载功能)

    好久没上,人都变的懒了...要逐渐把Blog捡起来了!最近接触到.Net,学习之余写一个自己一直想写的小工具,一是练练手,二是希望能方便更多的人,也希望能跟大家多交流,交流. 软件的功能是自动从网站上 ...

最新文章

  1. 程序、进程、线程区别与联系
  2. 卧槽!又一个Python神器!
  3. NR 5G PDCP分组数据汇聚协议
  4. Nutch爬虫引擎使用分析
  5. SQL注入之堆叠注入(sql-lab第38关)
  6. boost::random模块使用多精度类型测试所有与浮点相关的生成器和分布的测试程序
  7. Git 实用技巧记录,看这篇你就明白了!
  8. Shadow Properties之美(二)【Microsoft Entity Framework Core随笔】
  9. windows10上安装mysql
  10. 并查集——团伙(洛谷 P1892)
  11. cublas中执行矩阵乘法运算的函数 首先要注意的是cublas使用的是以列为主的存储方式,和c/c++中的以行为主的方式是不一样的。处理方法可参考下面的注释代码
  12. 如何在恢复模式下启动 Mac?
  13. TTL电平信号和RS232信号波形对比
  14. XTU (湘潭大学) 2011 新生练习赛(第一场)/ Problem B N! Last non zero
  15. uniApp微信小程序获取当前用户手机号码(前端)
  16. python+appium+android模拟器自动化测试 源码
  17. 二维数组 之 蛇形遍历
  18. ECharts - 14.小例子:实现日历图
  19. 电影步入下半年血拼关键期,这会是猫眼们持续破局的命门吗?
  20. kali WIFI破解实战

热门文章

  1. spark应用程序转换_Spark—RDD编程常用转换算子代码实例
  2. 处理相对时间(Day.js、Moment.js)(案例:结合vue的过滤器使用)
  3. 基于哈希表的索引堆变形(Hackerrank: QHEAP1)
  4. 牛客 奇怪的排序问题(单调栈/遍历)
  5. LeetCode MySQL 1194. 锦标赛优胜者
  6. LeetCode 725. 分隔链表
  7. LeetCode 1266. 访问所有点的最小时间(数学)
  8. java第九章编写一个能够产生_第九章java教程.ppt
  9. 亚马逊出的平板电脑_亚马逊推出了这款不到400元的平板电脑!学生党的福音!...
  10. 扔掉老破V100、A100,英伟达新一代计算卡H100来了!