winfrom更新
原理:
工具生成更新配置節(jié)xml放到文件服務(wù)器上,外網(wǎng)可訪問;
能過本地配置文件與服務(wù)器配置文件日期屬性對比及配置節(jié)版本與大小屬性判斷有無更新;
存在更新,將文件從服務(wù)器下載到客戶端,并替換原程序重啟;
實(shí)現(xiàn)時(shí),更新程序與原主程序是兩個(gè)不同的啟動程序,不存在文件占用,避免替換時(shí)文件被占用
如果做成一個(gè)程序,下載替換時(shí)需要通過外部批處理腳本關(guān)閉當(dāng)前應(yīng)用,并替換程序重啟應(yīng)用。在系統(tǒng)盤時(shí)要注意權(quán)限問題;
服務(wù)端生成xml代碼塊:
public partial class FormMain : Form{public FormMain(){InitializeComponent();txtWebUrl.Text = "localhost:8011";txtWebUrl.ForeColor = Color.Gray;}//獲取當(dāng)前目錄//string currentDirectory = AppDomain.CurrentDomain.BaseDirectory;string currentDirectory = System.Environment.CurrentDirectory;//服務(wù)端xml文件名稱string serverXmlName = "AutoupdateService.xml";//更新文件URL前綴string url = string.Empty;void CreateXml(){//創(chuàng)建文檔對象XmlDocument doc = new XmlDocument();//創(chuàng)建更新文件根節(jié)點(diǎn)XmlElement root = doc.CreateElement("Files");//設(shè)置更新節(jié)點(diǎn)日期root.SetAttribute("Date", DateTime.Now.ToString("yyyyMMdd"));////創(chuàng)建日期根節(jié)點(diǎn)//XmlElement versionDate = doc.CreateElement("UpDate");//versionDate.InnerText = DateTime.Now.ToString("yyyyMMdd");//doc.AppendChild(versionDate);//頭聲明XmlDeclaration xmldecl = doc.CreateXmlDeclaration("1.0", "utf-8", null);doc.AppendChild(xmldecl);DirectoryInfo dicInfo = new DirectoryInfo(currentDirectory);//調(diào)用遞歸方法組裝xml文件 PopuAllDirectory(doc, root, dicInfo);//追加節(jié)點(diǎn) doc.AppendChild(root);//保存文檔 doc.Save(serverXmlName);}//遞歸組裝xml文件方法private void PopuAllDirectory(XmlDocument doc, XmlElement root, DirectoryInfo dicInfo){foreach (FileInfo f in dicInfo.GetFiles()){//排除當(dāng)前目錄中生成服務(wù)端配置文件、此工具文件、后綴為pdb、config、ssk文件、包含vshost的文件List<string> notMimefile = new List<string>() { "pdb", "config", "ssk" };if (!f.Name.Contains("CreateXmlTools") && f.Name != "AutoupdateService.xml"&&f.Name != "AutoUpdater.exe" && !notMimefile.Contains(f.Name.Substring(f.Name.LastIndexOf(".") + 1)) && f.Name.IndexOf("vshost")==-1){string path = dicInfo.FullName.Replace(currentDirectory, "").Replace("\\", "/");string folderPath=string.Empty;if (path != string.Empty){folderPath = path.TrimStart('/') + "/";}XmlElement child = doc.CreateElement("File");child.SetAttribute("path", folderPath + f.Name);child.SetAttribute("url", url + path + "/" + f.Name);child.SetAttribute("version", FileVersionInfo.GetVersionInfo(f.FullName).FileVersion);child.SetAttribute("size", f.Length.ToString()); root.AppendChild(child);}}foreach (DirectoryInfo di in dicInfo.GetDirectories())PopuAllDirectory(doc, root, di);}private void btnCreate_Click(object sender, EventArgs e){string host = txtWebUrl.Text.Trim().TrimEnd('/').ToLower();url = (host.StartsWith("http") || host.StartsWith("https"))? host:"http://" + host;CreateXml();ReadXml();}private void ReadXml(){string path="AutoupdateService.xml";rtbXml.ReadOnly = true;if (File.Exists(path)){rtbXml.Text = File.ReadAllText(path);}}private void txtWebUrl_Enter(object sender, EventArgs e){txtWebUrl.ForeColor = Color.Black;if (txtWebUrl.Text.Trim() == "localhost:8011"){txtWebUrl.Text = string.Empty;}}}主程序更新相關(guān)代碼塊:
private static string strUpdateConfigPath = Application.StartupPath + @"\PrintLocal.config";private static string strUpdaterProPath = Application.StartupPath + @"\AutoUpdater.exe";//process.StartInfo.FileName = Application.StartupPath + "//AutoUpdater.exe";private PopTip _tip;private void PrintService_Load(object sender, EventArgs e){string strUpdateURL = GetConfigValue(strUpdateConfigPath, "ServerUrl");LocalVersion.Text = GetConfigValue(strUpdateConfigPath, "Date");RemoteVersion.Text = GetTheLastUpdateTime(strUpdateURL);skin.SkinFile = System.Environment.CurrentDirectory + @"\Skins\DeepCyan.ssk";System.Timers.Timer time =new System.Timers.Timer();int intervaltime = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["checkinterval"]);time.Elapsed +=new System.Timers.ElapsedEventHandler(IntervalCheck);time.Interval = intervaltime * 1000;//時(shí)間間隔為intervaltime秒鐘 time.Start();}private void IntervalCheck(object source, System.Timers.ElapsedEventArgs e){if (HasNewVersion()){_tip = new PopTip();Action c = () => _tip.ShowDialog();c.BeginInvoke(null, c);}}private void 更新ToolStripMenuItem_Click(object sender, EventArgs e){CheckUpdate();}/// <summary>/// 檢查更新./// </summary>private void CheckUpdateBt_Click(object sender, EventArgs e){CheckUpdate();}private void CheckUpdate() {if (HasNewVersion()) {if (MessageBox.Show("是否下載更新?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK){Process process = new Process();process.StartInfo.FileName = strUpdaterProPath;//更新程序所在位置 process.Start();//啟動更新程序 Process.GetCurrentProcess().Kill(); //Kill當(dāng)前程序 };}else{MessageBox.Show("未檢測到新版本.");}}#region 檢測版本與獲取版本信息internal static bool HasNewVersion(){bool hasNewVersion = false;string strUpdateURL = GetConfigValue(strUpdateConfigPath, "ServerUrl"); //讀取本地xml中配置的更新服務(wù)器的URLstring strLastUpdateDate = GetConfigValue(strUpdateConfigPath, "Date"); //讀取本地Config中配置的最近配置日期bool ConfigEnabled = Convert.ToBoolean(GetConfigValue(strUpdateConfigPath, "Enabled"));string strTheUpdateDate = GetTheLastUpdateTime(strUpdateURL); //獲得更新服務(wù)器端的此次更新日期if (ConfigEnabled && (DateTime.Compare(DateTime.ParseExact(strTheUpdateDate, "yyyyMMdd", null), DateTime.ParseExact(strLastUpdateDate, "yyyyMMdd", null)) > 0)){hasNewVersion = true;}return hasNewVersion;}internal static string GetConfigValue(string path, string appKey){XmlDocument xDoc = new XmlDocument();XmlNode xNode;XmlElement xElem = null;try{xDoc.Load(path);xNode = xDoc.SelectSingleNode("//Config");xElem = (XmlElement)xNode.SelectSingleNode(appKey);}catch (XmlException ex){MessageBox.Show(ex.Message);}if (xElem != null)return xElem.InnerText;elsereturn "";}private static string GetTheLastUpdateTime(string path){string Date = "";var xml = string.Empty;HttpWebRequest request = WebRequest.Create(path) as HttpWebRequest;var response = request.GetResponse();using (var stream = response.GetResponseStream()){using (var reader = new StreamReader(stream, Encoding.UTF8)){xml = reader.ReadToEnd();}}response.Close();var element = XElement.Parse(xml);Date = element.Attribute("Date").Value;return Date;}#endregionPopTip代碼塊:
public partial class PopTip : Form{ public PopTip(){InitializeComponent(); }private int _count;private void OKBt_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e){Hide();Process process = new Process();process.StartInfo.FileName = Application.StartupPath + @"\AutoUpdater.exe";//更新程序所在位置 //process.StartInfo.FileName = Application.StartupPath + "//AutoUpdater.exe";//更新程序所在位置 process.Start();//啟動更新程序 Process.GetCurrentProcess().Kill();}private void CancelBt_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e){Hide();}private void PopTip_Load(object sender, EventArgs e){Location = new Point(Screen.PrimaryScreen.Bounds.Width - Width, Screen.PrimaryScreen.Bounds.Height - Height-40);TipLb.Text = "發(fā)現(xiàn)新版本,是否馬上更新";OKBt.Text = "是,馬上更新";timer1.Start();}private void timer1_Tick(object sender, EventArgs e){_count++;//提示信息顯示8秒就關(guān)閉if (_count == 8){Close();}// timer1.Stop(); }}更新程序相關(guān)代碼塊:
/// <summary>/// Class Config/// </summary>public class Config{public bool Enabled { get; set; }public string ServerUrl { get; set; }public string Date { get; set; }public List<LocalFile> Files { get; set; }/// <summary>/// Loads the config./// </summary>/// <param name="file">The file.</param>/// <returns>Config.</returns>public static Config LoadConfig(string file){Config config=new Config();if (File.Exists(file)){var xs = new XmlSerializer(typeof(Config));var sr = new StreamReader(file);config = xs.Deserialize(sr) as Config;// 這里是序列化 sr.Close();}return config;}/// <summary>/// Saves the config./// </summary>/// <param name="file">The file.</param>public void SaveConfig(string file){var xs = new XmlSerializer(typeof(Config));var sw = new StreamWriter(file);xs.Serialize(sw, this);sw.Close();}}public class LocalFile{[XmlAttribute("path")]public string Path { get; set; }[XmlAttribute("version")]public string Version { get; set; }[XmlAttribute("size")]public long Size { get; set; }} public class RemoteFile{public string Path { get; set; }public string Url { get; set; }public string Version { get; set; }public long Size { get; set; }} public VersionDetails LoadNewVersion(){var xml = string.Empty;HttpWebRequest request = WebRequest.Create(this.ServerUrl) as HttpWebRequest;var response = request.GetResponse();using (var stream = response.GetResponseStream()){using (var reader = new StreamReader(stream, Encoding.UTF8)){xml = reader.ReadToEnd();}}response.Close();return new VersionDetails(xml);} public class VersionDetails{public VersionDetails(string xml){var element = XElement.Parse(xml); Date = element.Attribute("Date").Value;Files = this.LoadFiles(element);}public string Date{get;internal set;} public List<RemoteFile> Files{get;internal set;}private List<RemoteFile> LoadFiles(XElement element){var files = new List<RemoteFile>();foreach (var el in element.Elements("File")){var file = new RemoteFile(){Path = el.Attribute("path").Value,Url = el.Attribute("url").Value,Version = el.Attribute("version").Value,Size = Convert.ToInt64(el.Attribute("size").Value) };files.Add(file);}return files;}} public bool HasNewVersion{get{return LocalVersion.Enabled && (NewVersion.Date != LocalVersion.Date);}}http://blog.csdn.net/learning_hard/article/details/17456751 ? ?[你必須知道的異步編程]——基于任務(wù)的異步模式 ?異步下載
文件下載時(shí)可采用WebRequest或WebClient下載文件
參考:
http://www.cnblogs.com/KnightsWarrior/archive/2010/10/20/1856255.html#!comments
http://www.cnblogs.com/stoneniqiu/p/3806558.html
http://www.cnblogs.com/iyond/archive/2007/06/14/783301.html
http://www.cnblogs.com/sparkdev/p/6031920.html
winform更新解決辦法:
思路一:
生成一個(gè)批處理文件
執(zhí)行批處理文件并且自身退出
批處理文件中執(zhí)行覆蓋操作
批處理中最后一句啟動本程序
完成更新
思路二:
主程序A更新自動更新程序B,自動更新程序B更新主程序A
?
C# Timer用法及實(shí)例詳解 ?http://developer.51cto.com/art/200909/149829.htm
System.Timers.Timer t = new System.Timers.Timer(10000); //實(shí)例化Timer類,設(shè)置間隔時(shí)間為10000毫秒; t.Elapsed += new System.Timers.ElapsedEventHandler(theout); //到達(dá)時(shí)間的時(shí)候執(zhí)行事件; t.AutoReset = true; //設(shè)置是執(zhí)行一次(false)還是一直執(zhí)行(true); t.Enabled = true; //是否執(zhí)行System.Timers.Timer.Elapsed事件; public void theout( object source, System.Timers.ElapsedEventArgs e) { MessageBox.Show("OK!"); }?
Timer timer1 = new Timer();timer1.Interval = 1000;timer1.Enabled = true;timer1.Tick += new EventHandler(timer1EventProcessor);//添加事件https://msdn.microsoft.com/zh-cn/library/3840csdc.aspx Timer.Tick 事件?
http://www.cnblogs.com/ManchesterUnitedFootballClub/p/4596465.html ?Winfrom 提示消息框公共類
?
關(guān)于退出程序
this.Close();???只是關(guān)閉當(dāng)前窗口,若不是主窗體的話,是無法退出程序的,另外若有托管線程(非主線程),也無法干凈地退出;?
Application.Exit(); 方法停止在所有線程上運(yùn)行的所有消息循環(huán),并關(guān)閉應(yīng)用程序的所有窗口
強(qiáng)制直接退出了整個(gè)程序,不只是關(guān)閉子窗體:
Process.GetCurrentProcess().Kill(); ? ??//終止當(dāng)前正在運(yùn)行的線程
或者System.Threading.Thread.CurrentThread.Abort();
或者Application.ExitThread();
System.Environment.Exit(0);???這是最徹底的退出方式,不管什么線程都被強(qiáng)制退出,把程序結(jié)束的很干凈。?
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
- 上一篇: ngui 输入事件处理
- 下一篇: 关于meta的各种用处以及移动端的常见问