c# winform 自动升级
客户端思路:
1、新建一个配置文件Update.ini,用来存放软件的客户端版本:
[update] version=2011-09-09 15:26
2、新建一个单独的客户端升级程序Update.exe:
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.Threading;
using System.Diagnostics;
using System.IO;
namespace Update
{
publicpartialclassFrmUpdate : Form
{
//关闭进度条的委托
publicdelegatevoidCloseProgressDelegate();
//声明关闭进度条事件
publiceventCloseProgressDelegate CloseProgress;
UpdateService.Service service = null;//webservice服务
WebClient wc = null;
string url;//获取下载地址
string[] zips;//获取升级压缩包
int zipsIndex = 0;//当前正在下载的zips下标
long preBytes = 0;//上一次下载流量
long currBytes = 0;//当前下载流量
public FrmUpdate()
{
InitializeComponent();
service = new UpdateService.Service();//webservice服务
url = service.GetUrl();//获取下载地址
zips = service.GetZips();//获取升级压缩包
}
privatevoid FrmUpdate_Load(object sender, EventArgs e)
{
try
{
//用子线程工作
Thread t = newThread(newThreadStart(DownLoad));
t.IsBackground = true;//设为后台线程
t.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// 下载更新
/// </summary>
privatevoid DownLoad()
{
try
{
CloseProgress += newCloseProgressDelegate(FrmUpdate_CloseProgress);
if (zips.Length > 0)
{
wc = newWebClient();
wc.DownloadProgressChanged += newDownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
wc.DownloadFileCompleted += newAsyncCompletedEventHandler(wc_DownloadFileCompleted);
wc.DownloadFileAsync(newUri(url + zips[zipsIndex]), zips[zipsIndex]);
}
else
{
FrmUpdate_CloseProgress();//调用关闭进度条事件
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// 下载完成后触发
/// </summary>
void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
zipsIndex++;
if (zipsIndex < zips.Length)
{
//继续下载下一个压缩包
wc = newWebClient();
wc.DownloadProgressChanged += newDownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
wc.DownloadFileCompleted += newAsyncCompletedEventHandler(wc_DownloadFileCompleted);
wc.DownloadFileAsync(newUri(url + zips[zipsIndex]), zips[zipsIndex]);
}
else
{
//解压
int maximum = ZipClass.GetMaximum(zips);
foreach (string zip in zips)
{
ZipClass.UnZip(Application.StartupPath + @"\" + zip, "", maximum, FrmUpdate_SetProgress);
File.Delete(Application.StartupPath + @"\" + zip);
}
FrmUpdate_CloseProgress();//调用关闭进度条事件
}
}
/// <summary>
/// 下载时触发
/// </summary>
void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(newDownloadProgressChangedEventHandler(wc_DownloadProgressChanged), newobject[] { sender, e });
}
else
{
label1.Text = "正在下载自解压包" + zips[zipsIndex] + "(" + (zipsIndex + 1).ToString() + "/" + zips.Length + ")";
progressBar1.Maximum = 100;
progressBar1.Value = e.ProgressPercentage;
currBytes = e.BytesReceived;//当前下载流量
}
}
/// <summary>
/// 解压时进度条事件
/// </summary>
/// <param name="maximum">进度条最大值</param>
privatevoid FrmUpdate_SetProgress(int maximum, string msg)
{
if (this.InvokeRequired)
{
this.Invoke(new ZipClass.SetProgressDelegate(FrmUpdate_SetProgress), newobject[] { maximum, msg });
}
else
{
if (zipsIndex == zips.Length)
{
//刚压缩完
progressBar1.Value = 0;
zipsIndex++;
}
label1.Text = "正在解压" + msg + "(" + (progressBar1.Value + 1).ToString() + "/" + maximum + ")";
progressBar1.Maximum = maximum;
progressBar1.Value++;
}
}
/// <summary>
/// 实现关闭进度条事件
/// </summary>
privatevoid FrmUpdate_CloseProgress()
{
if (this.InvokeRequired)
{
this.Invoke(newCloseProgressDelegate(FrmUpdate_CloseProgress), null);
}
else
{
if (wc != null)
{
wc.Dispose();
}
if (zips.Length > 0)
{
MessageBox.Show("升级成功!");
}
else
{
MessageBox.Show("未找到升级包!");
}
IniClass ini = new IniClass(Application.StartupPath + @"\Update.ini");
string serviceVersion = service.GetVersion();//服务端版本
ini.IniWriteValue("update", "version", serviceVersion);//更新成功后将版本写入配置文件
Application.Exit();//退出升级程序
Process.Start("Main.exe");//打开主程序Main.exe
}
}
//1秒计算一次速度
privatevoid timer1_Tick(object sender, EventArgs e)
{
this.Text = ((currBytes - preBytes) / 1024).ToString() + "kb/s";//速度
preBytes = currBytes;//上一次下载流量
}
}
}
解压类ZipClass.cs:引用 ICSharpCode.SharpZipLib.dll
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using ICSharpCode.SharpZipLib;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip;
namespace Update
{
publicclassZipClass
{
//设置进度条的委托
publicdelegatevoidSetProgressDelegate(int maximum, string msg);
#region 解压
/// <summary>
/// 功能:解压zip格式的文件。
/// </summary>
/// <param name="zipFilePath">压缩文件路径,全路径格式</param>
/// <param name="unZipDir">解压文件存放路径,全路径格式,为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹</param>
/// <param name="err">出错信息</param>
/// <returns>解压是否成功</returns>
publicstaticbool UnZip(string zipFilePath, string unZipDir, int maximum, SetProgressDelegate setProgressDelegate)
{
if (zipFilePath == string.Empty)
{
thrownew System.IO.FileNotFoundException("压缩文件不不能为空!");
}
if (!File.Exists(zipFilePath))
{
thrownew System.IO.FileNotFoundException("压缩文件: " + zipFilePath + " 不存在!");
}
//解压文件夹为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹
if (unZipDir == string.Empty)
unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), "");
if (!unZipDir.EndsWith("//"))
unZipDir += "//";
if (!Directory.Exists(unZipDir))
Directory.CreateDirectory(unZipDir);
try
{
using (ZipInputStream s = newZipInputStream(File.OpenRead(zipFilePath)))
{
ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null)
{
string directoryName = Path.GetDirectoryName(theEntry.Name);
string fileName = Path.GetFileName(theEntry.Name);
if (directoryName.Length > 0)
{
Directory.CreateDirectory(unZipDir + directoryName);
}
if (!directoryName.EndsWith("//"))
directoryName += "//";
if (fileName != String.Empty)
{
using (FileStream streamWriter = File.Create(unZipDir + theEntry.Name))
{
int size = 2048;
byte[] data = newbyte[2048];
while (true)
{
size = s.Read(data, 0, data.Length);
if (size > 0)
{
streamWriter.Write(data, 0, size);
}
else
{
setProgressDelegate(maximum, theEntry.Name);
break;
}
}
}
}
}//while
}
}
catch (Exception ex)
{
thrownewException(ex.Message);
}
returntrue;
}//解压结束
#endregion
publicstaticint GetMaximum(string[] zips)
{
int maximum = 0;
ZipInputStream s = null;
ZipEntry theEntry = null;
foreach (string zip in zips)
{
s = newZipInputStream(File.OpenRead(Application.StartupPath + @"\" + zip));
while ((theEntry = s.GetNextEntry()) != null)
{
if (Path.GetFileName(theEntry.Name) != "")
{
maximum++;
}
}
}
if (s != null)
{
s.Close();
}
return maximum;
}
}
}
3、将update.ini和Update.exe复制到主程序目录,主程序登录时判断客户端版本是否与服务端版本相同,如不同,则做升级:
IniClass ini = newIniClass(Application.StartupPath + @"\Update.ini");
UpdateService.Service service = new UpdateService.Service();
string clientVersion = ini.IniReadValue("update", "version");//客户端版本
string serviceVersion = service.GetVersion();//服务端版本
if (clientVersion != serviceVersion)
{
DialogResult dialogResult = MessageBox.Show("有新版本,是否更新?", "升级", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
if (dialogResult == DialogResult.OK)
{
Application.Exit();
Process.Start("Update.exe");
}
}
else
{
MessageBox.Show("已更新至最高版本!");
}
服务端思路:
1、新建一个Web Service,在Web.Config中配置:
<connectionStrings>
<!--版本号-->
<add name="version" connectionString="2011-09-20 15:17"/>
<!--下载地址-->
<add name="url" connectionString ="http://localhost:8546/WebSite/"/>
<!--下载目录,最好为一级目录免得麻烦-->
<add name="directory" connectionString ="UpdateFile"/>
</connectionStrings>
2、在Service.cs写入以下代码:
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;
using System.Configuration;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
publicclassService : System.Web.Services.WebService
{
public Service()
{
//如果使用设计的组件,请取消注释以下行
//InitializeComponent();
}
/// <summary>
/// 获取版本号
/// </summary>
/// <returns>更新版本号</returns>
[WebMethod]
publicstring GetVersion()
{
returnConfigurationManager.ConnectionStrings["version"].ConnectionString;
}
/// <summary>
/// 获取下载地址
/// </summary>
/// <returns>下载地址</returns>
[WebMethod]
publicstring GetUrl()
{
returnConfigurationManager.ConnectionStrings["url"].ConnectionString + ConfigurationManager.ConnectionStrings["directory"].ConnectionString + "/";
}
/// <summary>
/// 获取下载zip压缩包
/// </summary>
/// <returns>下载zip压缩包</returns>
[WebMethod]
publicstring[] GetZips()
{
string folder = HttpRuntime.AppDomainAppPath + ConfigurationManager.ConnectionStrings["directory"].ConnectionString;
string[] zips = Directory.GetFileSystemEntries(folder);
for (int i = 0; i < zips.Length; i++)
{
zips[i] = Path.GetFileName(zips[i]);
}
return zips;
}
}
c# winform 自动升级的更多相关文章
- 分享一个客户端程序(winform)自动升级程序,思路+说明+源码
做winform的程序,不管用没用过自动更新,至少都想过自动更新是怎么实现的. 我这里共享一个自动更新的一套版本,给还没下手开始写的人一些帮助,也希望有大神来到,给指点优化意见. 本初我是通过sock ...
- winform 自动升级
自动升级系统OAUS的设计与实现(续) (附最新源码) http://www.cnblogs.com/zhuweisky/p/4209058.html Winform在线更新 http://www.c ...
- C/S WinForm自动升级
这二天刚好完成一个C/S 自动升级的功能 代码分享一下 /// <summary> /// 版本检测 /// </summary> public class ...
- winform自动升级方案
未涉及过winform升级,研究一阵,大致出来个不成熟的方案. 我的解决方案(判断升级,升级程序下载安装包的压缩包,解压,自动安装,重新启动程序). 1.首先根据服务器中软件版本号和本地软件版本号是否 ...
- 黄聪:C#Winform程序如何发布并自动升级(图解)
有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解)其实打包是打包,发 ...
- 【转】C#Winform程序如何发布并自动升级(图解)
有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解)其实打包是打包,发 ...
- C#Winform程序如何发布并自动升级(图解)
C#Winform程序如何发布并自动升级(图解) 有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布 关于打包的大家可以看我的文章C# w ...
- SNF开发平台WinForm之八-自动升级程序部署使用说明-SNF快速开发平台3.3-Spring.Net.Framework
9.1运行效果: 9.2开发实现: 1.首先配置服务器端,把“SNFAutoUpdate2.0\服务器端部署“目录按网站程序进行发布到IIS服务器上. 2.粘贴语句,生成程序 需要调用的应用程序的Lo ...
- 在WinForm中使用Web Service来实现软件自动升级
来源:互联网 winform程序相对web程序而言,功能更强大编程更方便,但软件更新却相当麻烦,要到客户端一台一台地升级,面对这个实际问题,在最近的一个小项目中,本人设计了一个通过软件实现自动升级技术 ...
随机推荐
- windows中80端口被System占用,PID=4的问题
在windows中如果tomcat需要使用80端口,发现该端口已经被占用,而netstat -ano发现该80端口被一个System的进程占用了,而PID=4.我们可以通过下面的方式找到对应的进程,然 ...
- CSS学习笔记01 CSS简介
1.CSS定义 CSS 指层叠样式表 (Cascading Style Sheets),是一种样式表语言,用来描述 HTML 或 XML(包括如 SVG.XHTML 之类的 XML 分支语言)文档的呈 ...
- Java使用递归的方法进行冒泡排序
对于递归来说,我只了解它的概念,没有具体使用过,近期也是尝试着用递归写了一下冒泡排序和大家分享,希望能帮助大家了解递归 递归是什么?通俗的讲:在方法内部调用自己 花了几分钟整出来的,下面是递归冒泡排序 ...
- 使用Hibernate Validator来帮你做数据校验
数据校验是贯穿所有应用程序层(从表示层到持久层)的常见任务.通常在每个层中实现相同的验证逻辑,这是耗时且容易出错的.这里我们可以使用Hibernate Validator来帮助我处理这项任务.对此,H ...
- Docker入门及基本指令
Docker概念 Docker就相当于一个Github账号,不过最开始的工程不能自己建立,要从DockerHub这个中央仓库pull过来,这个工程Docker称之为image,这个image竟然是个l ...
- Python标准库--UUID
UUID(Universally Unique Identifier)是128位通用唯一识别码,通常由32字节的字符串表示.它可以保证时间和空间的唯一性,也称为GUID,全称为:UUID —— Uni ...
- jQuery的$.getScript方法去加载javaScript文档解析
1.两个文件的代码如下: <script> function Ajax(){ //将9-4.html中的Ajax()函数进行修改 $.getScript('9-8.js',function ...
- AMD与CMD的异同
AMD与CMD的异同? 1.从官方推荐的写法上面得出: CMD ----- 依赖就近 //CMD define(function(require,exports,module){ var a = re ...
- 老男孩教育python全栈第九期视频
失效了在下面评论即可,会及时更新.python9期已全部更新完 链接: https://pan.baidu.com/s/1VV8_ZyVasK05iKd7QMxO-A 密码: 9zau
- Python+Selenium笔记(九):操作警告和弹出框
#之前发的 driver.switch_to_alert() 这句虽然可以运行通过,但是会弹出警告信息(这种写法3.x不建议使用) 改成 driver.switch_to.alert就不会了. (一 ...