• 在WinForm中使用Web Service来实现软件自动升级


     

    来源:互联网

    winform程序相对web程序而言,功能更强大编程更方便,但软件更新却相当麻烦,要到客户端一台一台地升级,面对这个实际问题,在最近的一个小项目中,本人设计了一个通过软件实现自动升级技术方案,弥补了这一缺陷,有较好的参考价值。

    一、升级的好处

    长期以来,广大程序员为到底是使用Client/Server,还是使用Browser/Server结构争论不休,在这些争论当中,C/S结构的程序的可维护性差,布置困难,升级不方便,维护成本高就是一个相当重要的因素,也是那些B/S支持者们把Client/Server

    结构打入地狱的一个重要原因。现在好了,我们就在最新的基于Microsoft的WinForm上用Web Service来实现软件的自动升级功能。

    二、升级的技术原理

    升级的原理有好几个,首先无非是将现有版本与最新版本作比较,发现最新的则提示用户是否升级。当然也有人用其它属性比较的,例如:文件大小,或者更新日期。而实现的方法呢?在VB时代,我使用的是XmlHTTP+INet控件。用XmlHTTP获取信息,用INET传输升级文件,而用一个简单的BAT文件来实现升级。而BAT文件有个特性,是可以删除自己本身。

    三、在.Net时代的实现

    在.Net时代,我们就有了更多的选择,可以使用WebRequest,也可以使用Web Service。在这里我们将用Web Service来实现软件的自动升级。实现原理:在Web Service中实现一个GetVer的WebMethod方法,其作用是获取当前的最新版本。然后将现在版本与最新版本比较,如果有新版本,则进行升级。步骤如下:

    1.准备一个作为升级模板用的xml文件(update.xml)。

    <?xml version="1.0" encoding="utf-8" ?>
    <product>
     <version>1.0.1818.42821</version>
     <description>修正一些Bug</description>
     <filelist count="4" sourcepath="./update/">
    <item name="City.xml" size="">
    <value />
    </item>
    <item name="CustomerApplication.exe" size="">
    <value />
    </item>
    <item name="Interop.SHDocVw.dll" size="">
    <value />
    </item>
    <item name="Citys.xml" size="">
    <value />
    </item>
     </filelist>
    </product>

    2.Web Service的GetVer方法。

    [WebMethod(Description="取得更新版本")]
    public string GetVer()
    {
    XmlDocument doc = new XmlDocument();
    doc.Load(Server.MapPath("update.xml"));
    XmlElement root = doc.DocumentElement;
    return root.SelectSingleNode("version").InnerText;
    }

    3.Web Service的GetUpdateData方法。

    [WebMethod(Description="在线更新软件")]
    [SoapHeader("sHeader")]
    public System.Xml.XmlDocument GetUpdateData()
    {
     //验证用户是否登陆
     if(sHeader==null) return null;
     if(!DataProvider.GetInstance.CheckLogin(sHeader.Username,sHeader.Password)) return null;
     //取得更新的xml模板内容
     XmlDocument doc = new XmlDocument();
     doc.Load(Server.MapPath("update.xml"));
     XmlElement root = doc.DocumentElement;
     //看看有几个文件需要更新
     XmlNode updateNode = root.SelectSingleNode("filelist");
     string path = updateNode.Attributes["sourcepath"].Value;
     int count = int.Parse(updateNode.Attributes["count"].Value);
     //将xml中的value用实际内容替换
     for(int i=0;i<count;i++)
     {
    XmlNode itemNode = updateNode.ChildNodes[i];
    string fileName = path + itemNode.Attributes["name"].Value;
    FileStream fs = File.OpenRead(Server.MapPath(fileName));
    itemNode.Attributes["size"].Value = fs.Length.ToString();
    BinaryReader br = new BinaryReader(fs);
    //这里是文件的实际内容,使用了Base64String编码
    itemNode.SelectSingleNode("value").InnerText =
    Convert.ToBase64String(br.ReadBytes((int)fs.Length),0,(int)fs.Length);
    br.Close();
    fs.Close();
     }
    return doc;
    }

    4.在客户端进行的工作。

    首先引用此Web Service,例如命名为:WebSvs

    string nVer = Start.GetService.GetVer(); 
    if(Application.ProductVersion.CompareTo(nVer)<=0) update();

    在本代码中Start.GetService是WebSvs的一个Static实例。
    首先检查版本,将结果与当前版本进行比较,如果为新版本则执行update方法。

    void update()
    {
    this.statusBarPanel1.Text = "正在下载...";
    System.Xml.XmlDocument doc = ((System.Xml.XmlDocument)Start.GetService.GetUpdateData());
    doc.Save(Application.StartupPath + @"update.xml");
    System.Diagnostics.Process.Start(Application.StartupPath + @"update.exe");
    Close();
    Application.Exit();
    }

    这里为了简单起见,没有使用异步方法,当然使用异步方法能更好的提高客户体验,这个需要读者们自己去添加。
    update的作用是将升级的XML文件下载下来,保存为执行文件目录下的一个update.xml文件。
    任务完成,退出程序,等待update.exe 来进行升级。

    5.update.exe的内容。

    private void Form1_Load(object sender, System.EventArgs e)
    {
        System.Diagnostics.Process[] ps = System.Diagnostics.Process.GetProcesses();
        foreach(System.Diagnostics.Process p in ps)
        {
            //MessageBox.Show(p.ProcessName);
            if(p.ProcessName.ToLower()=="customerapplication")
            {
                p.Kill();
                break;
            }
        }
        XmlDocument doc = new XmlDocument();
        doc.Load(Application.StartupPath + @"update.xml");
        XmlElement root = doc.DocumentElement;
        XmlNode updateNode = root.SelectSingleNode("filelist");
        string path = updateNode.Attributes["sourcepath"].Value;
        int count = int.Parse(updateNode.Attributes["count"].Value);
        for(int i=0;i<count;i++)
        {
            XmlNode itemNode = updateNode.ChildNodes[i];
            string fileName = itemNode.Attributes["name"].Value;
            FileInfo fi = new FileInfo(fileName);
            fi.Delete();
            //File.Delete(Application.StartupPath + @"" + fileName);
            this.label1.Text = "正在更新: " + fileName + " (" + itemNode.Attributes["size"].Value + ")...";
            FileStream fs = File.Open(fileName,FileMode.Create,FileAccess.Write);
            fs.Write(System.Convert.FromBase64String(itemNode.SelectSingleNode("value").InnerText),
                     0,int.Parse(itemNode.Attributes["size"].Value));
            fs.Close();
        }
        label1.Text = "更新完成";
        File.Delete(Application.StartupPath + @"update.xml");
        label1.Text = "正在重新启动应用程序...";
        System.Diagnostics.Process.Start("CustomerApplication.exe");
        Close();
        Application.Exit();
    }

    这个代码也很容易懂,首先就是找到主进程,如果没有关闭,则用Process.Kill()来关闭主程序。然后则用一个XmlDocument来Load程序生成的update.xml文件。用xml文件里指定的路径和文件名来生成指定的文件,在这之前先前已经存在的文件删除。更新完毕后,则重新启动主应用程序。这样更新就完成了。

    四、总结:

    从这个实例看来,Web Service的工作是很简单的,也是很容易实现的。好好的使用Web Service能够为我们的程序带来很多新的,强的功能。总而言之,.Net是易用的,强大的语言。

  • 相关阅读:
    Note/Solution 转置原理 & 多点求值
    Note/Solution 「洛谷 P5158」「模板」多项式快速插值
    Solution 「CTS 2019」「洛谷 P5404」氪金手游
    Solution 「CEOI 2017」「洛谷 P4654」Mousetrap
    Solution Set Border Theory
    Solution Set Stirling 数相关杂题
    Solution 「CEOI 2006」「洛谷 P5974」ANTENNA
    Solution 「ZJOI 2013」「洛谷 P3337」防守战线
    Solution 「CF 923E」Perpetual Subtraction
    KVM虚拟化
  • 原文地址:https://www.cnblogs.com/sczw-maqing/p/3370104.html
Copyright © 2020-2023  润新知