博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
winform应用程序更新 带进度条
阅读量:5748 次
发布时间:2019-06-18

本文共 9417 字,大约阅读时间需要 31 分钟。

 

winform程序相对web程序而言,功能更强大,编程更方便,但软件更新却相当麻烦,要到客户端一台一台地升级,面对这个实际问题。

程序exe自己下载覆盖自己肯定是不行的,会报“当前程序正在被另一个进程所使用”的系统错误。因此我们需要做一个专门更新的程序来下载更新主程序以及其他相关文件。

在最近的一个小项目中,本人设计了一个通过软件实现自动升级技术方案,弥补了这一缺陷,有较好的参考价值

实现原理:主程序通过在WebServices中实现一个GetVersion方法或是直接访问服务器端的UpdateList.xml,获取服务器上的最新版本。 然后将现在版本与最新版本比较,如果有新版本或存在新添加的文件则下载文件。

解决方案:

首先准备一个UpdateList.xml文件。文件中包含程序中各个文件的基本信息。

Ver:版本号 

Name:文件名 

Url:文件在程序中的路径

程序自动更新
http://localhost/testserver/
2014-06-05
   

 储存文件的实体类

/// /// 程序文件/// class UpFile{    public string Name { get; set; }//文件名    public string Version { get; set; }//版本号    public string Url { get; set; }//本地路径}

 主程序检查更新

class ProUpdate{    static string isCheck = "//Configuration//IsCheck";    static string xmlIP = "//Configuration//ServerConfig//IP";    static string xmlPort = "//Configuration//ServerConfig//Port";    static string xmlFile = "//AutoUpdater//Files";     ///      /// 获取更新文件集合     ///      /// 
需要文件
public static List
CheckUpdate() { List
fileList = new List
(); XmlDocument XmlSerDoc = new XmlDocument(); //在配置文件中获取服务器IP和端口号 string ip = XmlHelper.GetXmlAttribute(PublicMembers.XmlSysDoc, xmlIP, "value").Value; string port = XmlHelper.GetXmlAttribute(PublicMembers.XmlSysDoc, xmlPort, "value").Value; //读取服务器端UpdateList.xml XmlSerDoc.Load("http://" + ip + ":" + port + "/XKGL/checkUpdate/UpdateList.xml"); //获取服务器端UpdateList.xml中的Files XmlNodeList nodeSerList = XmlSerDoc.SelectSingleNode(xmlFile).ChildNodes; XmlDocument XmlLocDoc = new XmlDocument(); //读取本地UpdateList.xml XmlLocDoc.Load(Application.StartupPath + "\\Config\\UpdateList.xml"); //获取本地UpdateList.xml中的Files XmlNodeList nodeLocList = XmlLocDoc.SelectSingleNode(xmlFile).ChildNodes; //获得需要更新的文件 foreach (XmlNode nodeSer in nodeSerList) { string[] newVersion = nodeSer.Attributes["Ver"].Value.Split('.');//服务器版本数组 string[] oldVersion;//本地版本数组 string Ver = ""; string serName = nodeSer.Attributes["Name"].Value; string url = nodeSer.Attributes["Url"].Value; //服务器文件信息 UpFile file = new UpFile(); file.Name = serName; file.Version = nodeSer.Attributes["Ver"].Value; file.Url = url; //判断本地是否存在该文件 if (File.Exists(Application.StartupPath + url + serName)) { //获取本地文件版本 foreach (XmlNode nodeLoc in nodeLocList) { string locName = nodeLoc.Attributes["Name"].Value; if (serName.Equals(locName)) { Ver = nodeLoc.Attributes["Ver"].Value; break; } } //文件版本比较 if (!Ver.Equals("")) { oldVersion = Ver.Split('.'); for (int i = 0; i < 4; i++) { if (Convert.ToInt32(newVersion[i]) > Convert.ToInt32(oldVersion[i])) { fileList.Add(file); break; } } } } else { fileList.Add(file); } } return fileList; }}

 调用检查更新方法 

private delegate void dlLoadData();private void FrmProgress_Load(object sender, EventArgs e){    List
fileList = new List
(); //检查更新 fileList = ProUpdate.CheckUpdate(); Thread _bgThread = new Thread(() => { SyncProData(fileList); }); _bgThread.IsBackground = true; _bgThread.Start();}///
/// 下载更新/// ///
private void SyncProData(List
_updateFiles){ try { if (this.InvokeRequired) { Thread.Sleep(100); this.Invoke(new dlLoadData(() => { SyncProData(_updateFiles); })); } else { if (_updateFiles.Count > 0) { bool result = MessageBox.Show("发现新版本,是否更新", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes; if (result) { string strFileName = Newtonsoft.Json.JavaScriptConvert.SerializeObject(_updateFiles);                     /*                      * 在程序之间传递参数是JSON字符串中的“\"”引号会被过滤掉,用其他字符代替                      * */                     //打开更新程序,关闭主程序 System.Diagnostics.Process.Start(Application.StartupPath + "AutoUpdate.exe", strFileName.Replace("\"", "@@")); this.DialogResult = DialogResult.Yes; } } } } catch (Exception ex) { MessageBox.Show("更新失败。\n\r错误信息:" + ex.Message); }}

 

下面是AutoUpdate. exe更新程序的方法

 界面:

 

启动程序时接收主程序的参数 

static class Program{    ///     /// 应用程序的主入口点。    ///     [STAThread]    static void Main(String[] arg)    {
try { if (arg.Length == 0) { MessageBox.Show("该程序无法启动", "提示"); return; } string FilesInfo = arg[0].Replace("@@", "\"");//接收JSON串 FrmAutoUpdate frmAutoUpdate = new FrmAutoUpdate(FilesInfo); frmAutoUpdate.ShowDialog(); frmAutoUpdate.Dispose(); } catch (Exception ex) { MessageBox.Show(ex.Message); } }}

 

 页面显示需要更新的文件信息

/// /// 接收参数/// string strFileInfo = "";public FrmAutoUpdate(string _filesinfo){    InitializeComponent();    strFileInfo = _filesinfo;}private void FrmAutoUpdate_Load(object sender, EventArgs e){    List
update = new List
(); update = Newtonsoft.Json.JavaScriptConvert.DeserializeObject
>(strFileInfo);foreach (UpFile file in update) { ListViewItem lvi = new ListViewItem(); lvi.SubItems[0].Text = file.Name; lvi.SubItems.Add(file.Version); lvi.SubItems.Add("0%"); lvi.SubItems.Add(file.Url); lvwFileInfo.Items.Add(lvi); }}

 

 开始下载更新文件

private void btnUpdate_Click(object sender, EventArgs e){    Thread bgThread = new Thread(() =>    {        DownloadFile();    });    bgThread.IsBackground = true;    bgThread.Start();}public void DownloadFile(){    try    {        if (this.InvokeRequired)        {            Thread.Sleep(100);            this.Invoke(new dlLoadData(DownloadFile));        }        else        {            if (!gbxComplete.Visible)            {                XmlDocument XmlDoc = new XmlDocument();                XmlDoc.Load("Config\\Config.xml");//加载XML文档                for (int i = 0; i < lvwFileInfo.Items.Count; i++)                {                    string filename = lvwFileInfo.Items[i].SubItems[0].Text;                    string fileurl = lvwFileInfo.Items[i].SubItems[3].Text;                    string ip = GetXmlAttribute(XmlDoc, xmlIP, "value").Value;                    string port = GetXmlAttribute(XmlDoc, xmlPort, "value").Value;                    string serverFile = "http://" + ip + ":" + port + "/XKGL/checkUpdate/" + filename;                    string localFile = Application.StartupPath + fileurl + filename;                    httpDownload(serverFile, localFile, ProBar, lvwFileInfo.Items, i);                    lvwFileInfo.Items[i].SubItems[2].Text = "100%";                }                //下载                btnUpdate.Text = "完成";            }        }    }    catch    {        MessageBox.Show("文件下载出错,更新失败。", "警告", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);    }}/// /// 下载文件/// /// 服务器文件路径/// 本地文件路径/// 文件名/// 进度条控件/// ListView项/// countpublic void httpDownload(string URL, string LocalFile, System.Windows.Forms.ProgressBar prog, ListView.ListViewItemCollection item, int i){    float percent = 0;    System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL);    System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse();    long totalBytes = myrp.ContentLength;    if (prog != null)    {        prog.Maximum = (int)totalBytes;    }    System.IO.Stream st = myrp.GetResponseStream();    System.IO.Stream so = new System.IO.FileStream(LocalFile, System.IO.FileMode.Create);    long totalDownloadedByte = 0;    byte[] by = new byte[2048];    int osize = st.Read(by, 0, (int)by.Length);    while (osize > 0)    {        totalDownloadedByte = osize + totalDownloadedByte;        so.Write(by, 0, osize);        if (prog != null)        {            prog.Value = (int)totalDownloadedByte;        }        osize = st.Read(by, 0, (int)by.Length);        percent = (float)totalDownloadedByte / (float)totalBytes * 100;        if (percent.ToString().Length > 4)        {            item[i].SubItems[2].Text = percent.ToString().Substring(0, 5) + "%";        }        else        {            item[i].SubItems[2].Text = percent.ToString() + "%";        }        Application.DoEvents();    }    so.Close();    st.Close();}

 

 代码写完了,看一下效果

 

转载于:https://www.cnblogs.com/Mo-MaTure/p/4213241.html

你可能感兴趣的文章
hihoCoder #1015 : KMP算法
查看>>
php5全版本绕过open_basedir读文件脚本
查看>>
Python爬虫5-利用usergent伪装访问方式
查看>>
再看知名应用背后的第三方开源项目
查看>>
【深蓝】Volley 解读1
查看>>
ubuntu16.04下配置apache2与php
查看>>
linux下的不错的小软件:apvlv,zathura和vifm
查看>>
读书笔记之:C++ STL 开发技术导引-1
查看>>
匿名函数function前面的! ~等符号作用小解
查看>>
VC模拟鼠标的两种方式(SendMessage、mouse_event)
查看>>
react-router与react-router-dom使用时的区别
查看>>
bzoj 1634: [Usaco2007 Jan]Protecting the Flowers 护花
查看>>
java调用第三方包的例子
查看>>
ssm整合快速入门程序(三)之Data类型转换器
查看>>
代码d17
查看>>
内存管理原则
查看>>
Winform下KeyDown,KeyPress,KeyUp事件的总结
查看>>
android 一个TextView设置多种颜色
查看>>
mod_rewrite
查看>>
Hadoop相关知识整理系列之一:HBase基本架构及原理
查看>>