咱們在使用軟件的時候常常會遇到升級版本,這也是Winform程序的一個功能,今天就大概說下我是怎麼實現的吧(代碼有點不完美有小BUG,後面再說)node
先說下個人思路:首先在打開程序的時候去拿到我以前在網站上寫好的xml裏邊的版本號,判斷是否要更新,以後要更新的話就調用更新的exe(ps:這個是單獨出來的,由於更新確定要覆蓋當前的文件,文件運行的時候不能被覆蓋),而後下載最新的壓縮包到本地,調用7z解壓覆蓋便可服務器
思路明確了以後就開始寫代碼(因此說思路很重要啊!!!):
網絡
<?xml version="1.0" encoding="utf-8" ?> <Update> <Soft Name="BlogWriter"> <Verson>1.0.1.2</Verson> <DownLoad>http://www.shitong666.cn/BlogWrite.zip</DownLoad> </Soft> </Update>
這是xml,先放到服務器上去app
檢查更新的代碼(我把這個封裝成了一個類):ide
using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.IO; using System.Net; using System.Xml; namespace UpdateDemo { /// <summary> /// 程序更新 /// </summary> public class SoftUpdate { private string download; private const string updateUrl = "http://www.shitong666.cn/update.xml";//升級配置的XML文件地址 #region 構造函數 public SoftUpdate() { } /// <summary> /// 程序更新 /// </summary> /// <param name="file">要更新的文件</param> public SoftUpdate(string file, string softName) { this.LoadFile = file; this.SoftName = softName; } #endregion #region 屬性 private string loadFile; private string newVerson; private string softName; private bool isUpdate; /// <summary> /// 或取是否須要更新 /// </summary> public bool IsUpdate { get { checkUpdate(); return isUpdate; } } /// <summary> /// 要檢查更新的文件 /// </summary> public string LoadFile { get { return loadFile; } set { loadFile = value; } } /// <summary> /// 程序集新版本 /// </summary> public string NewVerson { get { return newVerson; } } /// <summary> /// 升級的名稱 /// </summary> public string SoftName { get { return softName; } set { softName = value; } } #endregion /// <summary> /// 檢查是否須要更新 /// </summary> public void checkUpdate() { try { WebClient wc = new WebClient(); Stream stream = wc.OpenRead(updateUrl); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(stream); XmlNode list = xmlDoc.SelectSingleNode("Update"); foreach (XmlNode node in list) { if (node.Name == "Soft" && node.Attributes["Name"].Value.ToLower() == SoftName.ToLower()) { foreach (XmlNode xml in node) { if (xml.Name == "Verson") newVerson = xml.InnerText;//拿到最新版本號 else download = xml.InnerText;//拿到要更新的文件(這塊不用拿的,懶得改了) } } } Version ver = new Version(newVerson); Version verson = Assembly.LoadFrom(loadFile).GetName().Version; int tm = verson.CompareTo(ver); //版本號比較 if (tm >= 0) isUpdate = false; else isUpdate = true; } catch (Exception ex) { throw new Exception("更新出現錯誤,請確認網絡鏈接無誤後重試!"); } } /// <summary> /// 獲取要更新的文件 /// </summary> /// <returns></returns> public override string ToString() { return this.loadFile; } } }
而後在主程序裏調用這個這檢查更新:函數
public partial class Form1 : Form { public Form1() { InitializeComponent(); this.Text = "Hello(版本1.0)"; label1.Text = "Hello World 1.0"; checkUpdate();//檢查更新 } public void checkUpdate() { SoftUpdate app = new SoftUpdate(Application.ExecutablePath, "BlogWriter"); try { if (app.IsUpdate && MessageBox.Show("檢查到新版本,是否更新?", "Update", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { //更新(調用更新的exe,這個是單獨的一個程序,下面再說怎麼寫) string fileName = Application.StartupPath+@"\Updata.exe"; Process p = new Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.FileName = fileName; p.StartInfo.CreateNoWindow = true; p.StartInfo.Arguments = "你好, 西安 歡迎你!";//參數以空格分隔,若是某個參數爲空,能夠傳入」」 p.Start();
System.Environment.Exit(System.Environment.ExitCode); //結束主線程
// p.WaitForExit(); //這裏就不能等他結束了
// string output = p.StandardOutput.ReadToEnd(); //this.Dispose();//關閉主程序
} } catch (Exception ex) { MessageBox.Show(ex.Message); } } }
下來就是下載更新的壓縮包了和解壓的exe了:優化
先看界面網站
public partial class UpdateForm : Form { public UpdateForm() { InitializeComponent(); this.button1.Enabled = false; this.button1.Click += button1_Click; this.Text = "更新..."; UpdateDownLoad(); // Update(); } void button1_Click(object sender, EventArgs e) { this.Close(); } public delegate void ChangeBarDel(System.Net.DownloadProgressChangedEventArgs e); private void UpdateDownLoad() { WebClient wc = new WebClient(); wc.DownloadProgressChanged += wc_DownloadProgressChanged; wc.DownloadFileAsync(new Uri("http://www.shitong666.cn/BlogWriter.zip"), "Update.zip");//要下載文件的路徑,下載以後的命名 } // int index = 0; void wc_DownloadProgressChanged(object sender, System.Net.DownloadProgressChangedEventArgs e) { Action act = () => { this.progressBar1.Value = e.ProgressPercentage; this.label1.Text = e.ProgressPercentage + "%"; }; this.Invoke(act); if (e.ProgressPercentage == 100) { //下載完成以後開始覆蓋 ZipHelper.Unzip();//調用解壓的類 this.button1.Enabled = true; } } }
解壓的類:this
public class ZipHelper { public static string zipFileFullName = "update.zip"; public static void Unzip() { string _appPath = new DirectoryInfo(Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName).Parent.FullName; string s7z = _appPath + @"\7-Zip\7z.exe"; System.Diagnostics.Process pNew = new System.Diagnostics.Process(); pNew.StartInfo.FileName = s7z; pNew.StartInfo.Arguments = string.Format(" x \"{0}\\{1}\" -y -o\"{0}\"", _appPath, zipFileFullName); //x "1" -y -o"2" 這段7z命令的意思: x是解壓的意思 "{0}"的位置寫要解壓文件路徑"{1}"這個1的位置寫要解壓的文件名 -y是覆蓋的意思 -o是要解壓的位置 pNew.Start(); //等待完成 pNew.WaitForExit();
//刪除壓縮包
File.Delete(_appPath + @"\" + zipFileFullName); } }
最後說bug吧!這個bug真心多,首先我拿不到解壓的進度,個人想法是讓更新的進度條停在90%左右等待解壓完成以後再走到100%,其他的再優化一下就應該能夠用了,最後謝謝hover大神給個人指導spa