C#软件自动更新程序
2019獨角獸企業重金招聘Python工程師標準>>>
?基于C#實現的軟件自動更新程序,之前在網上搜集了兩款軟件自動更新程序,在實際應用中,對部分BUG進行修復,添加+完善一些功能。這里,推薦給大家。代碼完全開放,可以根據實際應用場景,作調整。
先來看看第一款軟件自動更新程序的效果圖吧:
它的原理非常簡單,它是根據文件的日期,進行比較,然后在服務端修改生成一個XML文件,軟件在啟動的時候,驗證是否更新,如果需要更新,則終止主程序,啟動自動更新程序,更新成功后,再啟動主程序。
它的大體結構是這樣的:
1、需要一個網站,把需要更新的文件都存放在這個網站下的UpdateServer文件夾,它自身提供了一個生成更新配置文件的UpdateListBuilder.exe工具,只需點擊執行exe,便可在服務端生成更新所需的xml配置文件。格式如下:
<AutoUpdater><UpdateInfo><UpdateTime Date="2014-2-21" /><Version Num="1.0.0.0" /><UpdateSize Size="32046" /></UpdateInfo><UpdateFileList><UpdateFile>\K3SP.exe</UpdateFile><UpdateFile>\conf\menu.xml</UpdateFile></UpdateFileList> </AutoUpdater>這里的K3SP.exe是主程序exe。
2、主程序添加如下代碼:
/// <summary>/// 檢測更新/// </summary>private void checkUpdate(){strUpdateURL = getConfigValue(strUpdateXmlPath, "Url"); //讀取本地xml中配置的更新服務器的URLstring strLastUpdateDate = getConfigValue(strUpdateXmlPath, "UpDate"); //讀取本地xml中配置的最近一次更新日期if (strUpdateURL.Substring(strUpdateURL.Length - 1) != "/") //如果配置的xml中URL沒帶最后一個反斜杠,則加一下,防止出錯strUpdateURL += "/";strTheUpdateDate = getTheLastUpdateTime(strUpdateURL); //獲得更新服務器端的此次更新日期if (!String.IsNullOrEmpty(strTheUpdateDate) && !String.IsNullOrEmpty(strLastUpdateDate)) //日期都不為空{if (DateTime.Compare(Convert.ToDateTime(strTheUpdateDate, CultureInfo.InvariantCulture),Convert.ToDateTime(strLastUpdateDate, CultureInfo.InvariantCulture)) > 0) //字符轉日期,并比較日期大小{//本次更新日期 大于 最近一次更新日期,開始更新try{if (new K3SP.lib.ClassCheckProIsRun().checkProcess(strUpdaterProFileName, strUpdaterProPath)){classMsg.messageInfoBox("更新程序" + strUpdaterProFileName + "已打開!");}else{Process.Start(strUpdaterProPath);}}catch (Win32Exception ex){classMsg.messageInfoBox(ex.Message); //主程序未更新成功或者被誤刪掉,再更新一遍}Application.Exit(); //退出主程序}}}在窗體加載事件,調用checkUpdate方法進行檢測更新。
再來看看第二種自動更新的效果吧:
? ? ?該工具自身是英文的,在此基礎上,進行了部分漢化,又增加了AutoUpdateBuilder自動生成更新配置文件的程序,方便我們在服務端維護。
這里,我做了個簡單的demo程序。為使用改程序,我還新加了一個AutoUpdaterTool的工具,來進行軟件的升級更新。
先來,看看AutoUpdaterTool都做了些什么?
/// <summary>/// 應用程序的主入口點。/// </summary>[STAThread]static void Main(){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);//Application.Run(new Form1());#region check and download new version programbool bHasError = false;IAutoUpdater autoUpdater = new KnightsWarriorAutoupdater.AutoUpdater();//主程序執行路徑string strExePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AutoUpdaterDemo.exe");try{if (new ClassCheckProIsRun().checkProcessForProName(strExePath))//檢測主程序是否執行{MessageBox.Show(@"進程中檢測到主程序正在運行,請先關閉才可更新。");return;}autoUpdater.Update();}catch (WebException exp){MessageBox.Show(@"不能夠找到指定的資源!");bHasError = true;}catch (XmlException exp){bHasError = true;MessageBox.Show(@"下載升級文件時發生錯誤!");}catch (NotSupportedException exp){bHasError = true;MessageBox.Show(@"更新地址配置錯誤");}catch (ArgumentException exp){bHasError = true;MessageBox.Show(@"下載升級文件時發生錯誤");}catch (Exception exp){bHasError = true;MessageBox.Show(@"升級過程中發生錯誤!");}finally{if (bHasError == true){try{autoUpdater.RollBack();}catch (Exception){//Log the message to your file or database}}}#endregionSystem.Diagnostics.Process.Start(strExePath, ((KnightsWarriorAutoupdater.AutoUpdater)autoUpdater).isCancel.ToString());Application.Exit();}?
我建了一個Winform程序,不要窗口,檢測更新程序,都寫在了Main函數里。
接下來,在看看AutoUpdaterDemo示例程序的檢測方法:
/// <summary>/// /// </summary>public bool IsCancelUpdate { get; set; }/// <summary>/// 檢測更新/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Form1_Load(object sender, EventArgs e){if (!IsCancelUpdate) CheckUpdate();}/// <summary>/// 自動更新程序路徑/// </summary>private readonly string autoUpdaterPath = AppDomain.CurrentDomain.BaseDirectory + "AutoUpdaterTool.exe";/// <summary>/// 檢測更新程序/// </summary>void CheckUpdate(){try{IAutoUpdater autoUpdater = new KnightsWarriorAutoupdater.AutoUpdater();if (autoUpdater.CheckUpdate()){if (new lib.ClassCheckProIsRun().checkProcess(autoUpdaterPath)){MessageBox.Show(@"更新程序已經運行!");return;}System.Diagnostics.Process.Start(autoUpdaterPath);Application.Exit();}}catch (Exception exception){MessageBox.Show(exception.Message);}}注意:在這里,我給窗體新加了一個IsCancelUpdate的屬性,這個為下面的取消更新做了鋪墊。
這個AutoUpdaterDemo的入口函數,我添加了參數,來實現取消更新的功能。
/// <summary>/// 應用程序的主入口點。/// </summary>[STAThread]static void Main(string[] args){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);var mainForm = new Form1();if (args != null && args.Length > 0) mainForm.IsCancelUpdate = Convert.ToBoolean(args[0]);Application.Run(mainForm);}妙處就在這里。為什么要這么做?因為自動更新程序和主程序,是兩個進程,我們在主程序里檢測更新,如果客戶端取消更新,又會啟動主程序,主程序又會檢測更新,這樣形成了一個死循環。
這個參數,是通過自動更新工具AutoUpdaterTool.exe來傳遞的,代碼如下:
/// <summary>/// 應用程序的主入口點。/// </summary>[STAThread]static void Main(){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);//Application.Run(new Form1());#region check and download new version programbool bHasError = false;IAutoUpdater autoUpdater = new KnightsWarriorAutoupdater.AutoUpdater();//主程序執行路徑string strExePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AutoUpdaterDemo.exe");try{if (new ClassCheckProIsRun().checkProcessForProName(strExePath))//檢測主程序是否執行{MessageBox.Show(@"進程中檢測到主程序正在運行,請先關閉才可更新。");return;}autoUpdater.Update();}catch (WebException exp){MessageBox.Show(@"不能夠找到指定的資源!");bHasError = true;}catch (XmlException exp){bHasError = true;MessageBox.Show(@"下載升級文件時發生錯誤!");}catch (NotSupportedException exp){bHasError = true;MessageBox.Show(@"更新地址配置錯誤");}catch (ArgumentException exp){bHasError = true;MessageBox.Show(@"下載升級文件時發生錯誤");}catch (Exception exp){bHasError = true;MessageBox.Show(@"升級過程中發生錯誤!");}finally{if (bHasError == true){try{autoUpdater.RollBack();}catch (Exception){//Log the message to your file or database}}}#endregionSystem.Diagnostics.Process.Start(strExePath, ((KnightsWarriorAutoupdater.AutoUpdater)autoUpdater).isCancel.ToString());Application.Exit();就在這段代碼的最后,啟動這個進程的時候,我把取消isCancel這個屬性傳遞給主程序。
isCancel是我為AutoUpdater對象添加的一個屬性。
另外,我還為IAutoUpdater接口,公開了CheckUpdate方法,用來在AutoUpdaterDemo中,調用該方法,檢測是否需要更新。
再來看看,為自動生成更新配置文件的程序。注意:要想支持文件夾的更新,需要簡單的修改下代碼即可。
using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; /******************************************************************************************************************* * * 說 明: 生成自動更新配置文件(版本:Version1.0.0)* 作 者:李朝強* 日 期:2015/05/19* 修 改:* 參 考:http://my.oschina.net/lichaoqiang/* 備 注:暫無...* * * ***************************************************************************************************************/ namespace AutoUpdaterBuilder {class Program{/// <summary>/// <![CDATA[主程序入口]]>/// </summary>/// <param name="args"></param>static void Main(string[] args){Console.Title = "更新文檔生成工具!";try{//遠程服務器URLstring strServerUrl = System.Configuration.ConfigurationManager.AppSettings["ServerUrl"];//創建Xml文檔XmlDocument xml = new XmlDocument();var declaration = xml.CreateXmlDeclaration("1.0", "utf-8", null);xml.AppendChild(declaration);var root = xml.CreateElement("UpdateFileList");//根節點string strBaseDirectory = AppDomain.CurrentDomain.BaseDirectory;//應用程序根目錄string[] strFiles = Directory.GetFiles(strBaseDirectory);//獲取目錄下所有文件//版本信息Version v = new Version(System.Configuration.ConfigurationManager.AppSettings["Version"]);Version theNewVersion = new Version(v.Major, v.Minor, v.Build, v.Revision + 1);//生成新的版本號List<FileInfo> updataFileInfos = new List<FileInfo>();//更新文件列表//循環更新文件foreach (string strfile in strFiles){if (strfile.Contains("AutoUpdaterBuilder.exe") ||strfile.EndsWith(".xml") ||strfile.EndsWith(".config")) continue;//文件名FileInfo file = new FileInfo(strfile);var localFile = xml.CreateElement("LocalFile");localFile.SetAttribute("path", file.Name);localFile.SetAttribute("url", string.Format("{0}/{1}", strServerUrl, file.Name));localFile.SetAttribute("lastver", theNewVersion.ToString());localFile.SetAttribute("size", file.Length.ToString());localFile.SetAttribute("needRestart", "false");root.AppendChild(localFile);updataFileInfos.Add(file);ShowMessge("正在創建文件“{0}”的更新配置", file.Name);}xml.AppendChild(root);string strSaveToPath = System.IO.Path.Combine(strBaseDirectory, "AutoupdateService.xml");//配置文件保存路徑xml.Save(strSaveToPath);//更新日志string[] strUpdateLogs = Array.ConvertAll(updataFileInfos.ToArray(), (t) => string.Format("[{0}] {1}", t.LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss"), t.Name));File.WriteAllLines(Path.Combine(strBaseDirectory, "UpdateLog.txt"), strUpdateLogs);//修改配置文件ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();fileMap.ExeConfigFilename = System.IO.Path.Combine(strBaseDirectory, "AutoUpdaterBuilder.exe.config");System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);configuration.AppSettings.Settings["Version"].Value = theNewVersion.ToString();configuration.Save(ConfigurationSaveMode.Modified);Console.WriteLine("更新文件生成成功,2s后退出!");System.Threading.Thread.Sleep(2000);//線程休眠2s}catch (Exception exception){Console.WriteLine(exception.Message);Console.ReadLine();}}/// <summary>/// <![CDATA[輸出消息]]>/// </summary>/// <param name="format"></param>/// <param name="args"></param>static void ShowMessge(string format, params object[] args){Console.WriteLine(format, arg: args);}/// <summary>/// /// </summary>/// <param name="format"></param>/// <param name="args"></param>static void Log(string format, params object[] args){}} }生成后的xml文件
<?xml version="1.0" encoding="utf-8"?> <UpdateFileList><LocalFile path="AutoUpdater.dll" url="http://localhost:8833//AutoUpdater.dll" lastver="1.0.0.8" size="43520" needRestart="false" /><LocalFile path="AutoUpdaterDemo.exe" url="http://localhost:8833//AutoUpdaterDemo.exe" lastver="1.0.0.8" size="9728" needRestart="false" /><LocalFile path="phpStudy.rar" url="http://localhost:8833//phpStudy.rar" lastver="1.0.0.8" size="45633237" needRestart="false" /><LocalFile path="update.txt" url="http://localhost:8833//update.txt" lastver="1.0.0.8" size="45" needRestart="false" /><LocalFile path="新增測試文件.txt" url="http://localhost:8833//新增測試文件.txt" lastver="1.0.0.8" size="0" needRestart="false" /> </UpdateFileList>怎樣部署?
很簡單,首先,我們只需要建一個網站,把AutoUpdaterBuilder.exe和AutoUpdaterBuilder.exe.config文件放進去,然后再把需要更新的文件,放入改文件夾下。
<appSettings><remove key="ServerUrl"/><remove key="Version"/><add key="ServerUrl" value="http://localhost:8833/"/><add key="Version" value="1.0.0.1"/></appSettings>以上是AutoUpdaterBuilder.exe.config配置文件。
其次,在主程序上添加對AutoUpdater.dll的引用,主要是為了調用它的檢測更新方法。
今天就寫到這吧,感興趣的朋友,可以親手嘗試下。
轉載于:https://my.oschina.net/lichaoqiang/blog/866525
總結
以上是生活随笔為你收集整理的C#软件自动更新程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [JS] 动态修改ckPlayer播放器
- 下一篇: JavaScript事件对象