1. 程式人生 > >C# winForm 軟體自動升級實現方式

C# winForm 軟體自動升級實現方式

對於C#winform開發者來說,軟體自動升級功能是一個很重要的功能。作者根據自身經驗,和大家分享一下軟體升級的實現方式。

注意:本文主要介紹通過WebService升級軟體。作者的另一篇通過FTP方式升級軟體的介紹可在作者的另一篇文中檢視https://jingyan.baidu.com/article/4dc4084842d8fec8d946f1ca.html

第一步:首先建立一個Winform程式,這裡叫做AppUpdatePC.在Form1的.cs檔案中複製一下程式碼:這裡通過讀取主程式的檔案版本和升級包裡面的升級程式的檔案版本做匹配,來進行升級判斷。如果兩者程式版本一致,則進行升級,如果不一致,則不升級

       
        string url = " http://10.121.34.130:2272/update/pcapp/";這裡改為你的WebService地址。

        string fUpdate = @"";

        string AppName = "BarcodePrint";
        string m_workPath = "";
        string xmlFile = null;

        public Form1()
        {
            InitializeComponent();

            //m_workPath = Assembly.GetExecutingAssembly().GetName().CodeBase.Substring(0, Assembly.GetExecutingAssembly().GetName().CodeBase.LastIndexOf(@"/") + 1).Replace(@"file:///", "");


            //Release版本
            //m_workPath = System.IO.Path.GetFullPath(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
            //m_workPath = System.IO.Path.GetDirectoryName(m_workPath);
            m_workPath = AppDomain.CurrentDomain.BaseDirectory;
            //m_workPath = Application.StartupPath;
            //xmlFile = m_workPath;

            //MessageBox.Show(m_workPath);
            //string workPath = System.IO.Path.Combine(filePath, "Config.xml");

            //DataSet ds = new DataSet();
            //ds.ReadXml( m_workPath + "config.xml");
            //url = ds.Tables[0].Rows[0]["WebServiceURL"].ToString();
            //url = url.Substring(0, url.IndexOf("Service"));
            //url += "update/Update_TKE_HT/";
            //AppName = ds.Tables[0].Rows[0]["AppName"].ToString();

            
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Download();
        }
        private void Download()
        {
            //獲取本地應用程式目錄
            DirectoryInfo theFolder = new DirectoryInfo(Path.GetDirectoryName(this.m_workPath + "\\"));
            //獲取伺服器目錄
            //DirectoryInfo theFolder = new DirectoryInfo(fUpdate);

            try
            {
                this.button1.Enabled = false;
                this.button2.Enabled = false;
                this.Refresh();

                foreach (FileInfo theFile in theFolder.GetFiles())
                {
                    DownloadFile(theFile.Name, url + theFile.Name);
                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
            }
            finally
            {
                this.button1.Enabled = true;
                this.button2.Enabled = true; 
            }
            //啟動程式 
            System.Diagnostics.Process.Start(this.m_workPath + "\\" + AppName + ".exe", "");
            Application.Exit();
            Close();

        }
        private void DownloadFile(string FileName, string strUrl)
        {
            HttpWebRequest request;
            HttpWebResponse response = null;
            try
            {
                System.Globalization.DateTimeFormatInfo dfi = null;
                System.Globalization.CultureInfo ci = null;
                ci = new System.Globalization.CultureInfo("zh-CN");
                dfi = new System.Globalization.DateTimeFormatInfo();

                //WebRequest wr = WebRequest.Create("");

                //System.Net.WebResponse w=wr.
                DateTime fileDate;
                long totalBytes;
                DirectoryInfo theFolder = new DirectoryInfo(Path.GetTempPath() + "");
                string fileName = theFolder + FileName;

                request = (HttpWebRequest)HttpWebRequest.Create(strUrl);

                response = (HttpWebResponse)request.GetResponse();

                if (response == null)
                    return;
                fileDate = response.LastModified;
                //if (File.GetLastWriteTime(m_workPath+"\\"+FileName) >= fileDate)
                //{
                //    response.Close();
                //    return;
                //}
                totalBytes = response.ContentLength;
                progressBar1.Maximum = Convert.ToInt32(totalBytes);

                Stream stream = response.GetResponseStream();
                FileStream sw = new FileStream(fileName, FileMode.Create);
                int totalDownloadedByte = 0;
                Byte[] @by = new byte[1024];
                int osize = stream.Read(@by, 0, @by.Length);
                while (osize > 0)
                {
                    totalDownloadedByte = osize + totalDownloadedByte;
                    Application.DoEvents();
                    sw.Write(@by, 0, osize);
                    progressBar1.Value = totalDownloadedByte;
                    osize = stream.Read(@by, 0, @by.Length);
                }
                sw.Close();
                stream.Close();

                //System.Diagnostics.Process[] proc = System.Diagnostics.Process.GetProcessesByName(AppName);

                ////關閉原有應用程式的所有程序 
                //foreach (System.Diagnostics.Process pro in proc)
                //{
                //    pro.Kill();
                //}


                //DirectoryInfo theFolder = new DirectoryInfo(Path.GetTempPath() + "ysy");
                if (theFolder.Exists)
                {
                    foreach (FileInfo theFile in theFolder.GetFiles())
                    {
                        //如果臨時資料夾下存在與應用程式所在目錄下的檔案同名的檔案,則刪除應用程式目錄下的檔案 
                        if (File.Exists(this.m_workPath + "\\" + Path.GetFileName(theFile.FullName)))
                        {
                            File.Delete(this.m_workPath + "\\" + Path.GetFileName(theFile.FullName));
                            //將臨時資料夾的檔案移到應用程式所在的目錄下 
                            File.Move(theFile.FullName, this.m_workPath + "\\" + Path.GetFileName(theFile.FullName));

                        }
                    }
                }
                //File.SetLastWriteTime(FileName, fileDate);

            }
            catch (Exception)
            {
                if (response != null)
                    response.Close();
                //MessageBox.Show(ex.Message);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //System.Diagnostics.Process.Start(this.m_workPath + "\\" + AppName + ".exe");
            this.Close();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //Download();

        }

        public int setConfig(string pro, string par, string val)
        {
            XmlDocument xd = new XmlDocument();
            xd.Load(xmlFile);
            try
            {
                xd.FirstChild.SelectSingleNode(pro).SelectSingleNode(par).InnerText = val;

                xd.Save(xmlFile);
                xd = null;
                return 0;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.ToString());
            }
        }
        public int setParConfig(string ItemName, string ItemValue)
        {
            XmlDocument xd = new XmlDocument();
            xd.Load(xmlFile);
            try
            {
                xd.FirstChild.SelectSingleNode(ItemName).InnerText = ItemValue;

                xd.Save(xmlFile);
                xd = null;
                return 0;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.ToString());
            }
        }
        public string getConfig(string pro, string par)
        {
            XmlDocument xd = new XmlDocument();
            xd.Load(xmlFile);
            try
            {
                string str = xd.FirstChild.SelectSingleNode(pro).SelectSingleNode(par).InnerText;
                xd = null;
                return str;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.ToString());
            }
        }
      
        private string GetVersion()
        {
            string version = "";

            try
            {
                string strVersionPath = this.m_workPath + "version.txt";
                StreamReader sw = new StreamReader( strVersionPath );
                version = sw.ReadLine();
            }
            catch ( Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

            return version;
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            Download();
        }

       
    }

第二步:在系統登入時,進行系統的版本號判斷。這裡寫一個判斷版本號是否一致的方法,來進行版本號的匹配,該程式碼寫在WebService的實現程式碼中,中間的呼叫過程,大家可根據自己的專案自身情況,進行呼叫程式碼的編寫。判斷版本號一致的程式碼如下:

       public static bool VerifyVersion(string[] FileVersion, string[] FileName)
        {
            LogNote ln = null;

            try
            {
                string strVersion = null;
                ln = new LogNote(AppDomain.CurrentDomain.BaseDirectory + "barcode.log");
                for (int i = 0; i < FileName.Length; i++)
                {
                    FileVersionInfo fv = FileVersionInfo.GetVersionInfo(AppDomain.CurrentDomain.BaseDirectory + "\\update\\" + FileName[i]);
                    strVersion = fv.FileVersion;

                    //strVersion = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory+"\\update\\" + FileName[i]).GetName().Version.ToString();
                    //Version v = new Version("");
                    ln.Write(i.ToString(), FileVersion + "/" + strVersion);
                    if (FileVersion[i] != strVersion)
                    {
                        return false;
                    }
                }
                return true;
            }
            catch (Exception er)
            {
                return true;
            }

        }

WebService宣告的程式碼如下:

    [WebMethod]
    public bool verfiyVersion(string[] Version, string[] FileName)
    {
        return CommonDA.VerifyVersion(Version, FileName);
    }

WInform程式的介面實現程式碼如下:

        public bool verifyVersion(string[] Version, string[] FileName)
        {
            Common co = Common.GetCommon();
            return co.m_service.verfiyVersion(Version, FileName);
        }

winform程式的函式呼叫程式碼如下所示:

                string[] fileName = new string[2];
                string[] fileVersion = new string[2];

                fileName[0] = "\\htapp\\HTApp.exe";程式路徑
                fileVersion[0] = this.labversion.Text;
                //fileName[1] = "U8Business.dll";
                //fileVersion[1] = this.labDllversion.Text;

                if (!Common.CurrentUser.verifyVersion(fileVersion, fileName))
                {
                    MessageBox.Show("程式有新的版本,請確定後更新!");
                    System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName
                        (System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).ToString() + "\\AppUpdate.exe", "123");
                    Application.Exit();
                    Close();
                    return;
                }

第三步:修改程式版本號,完成升級包的製作。開啟主程式專案的目錄,點選“propertiey”,開啟AssmsblyInfo類,修改版本號的資訊,如下所示,修改之後儲存,重新生成程式,然後就可以把Bin/Debug目錄下的新程式放到WebService的相對應的更新目錄下。帶程式啟動時,會自動監測程式的版本號,並且進行升級。

// 程式集的版本資訊由下面四個值組成:
//
//      主版本
//      次版本 
//      內部版本號
//      修訂號
//
// 可以指定所有這些值,也可以使用“內部版本號”和“修訂號”的預設值,
// 方法是按如下所示使用“*”:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.2.2")]
[assembly: AssemblyFileVersion("1.2.2.2")]