ClickOnce DIY全自動(dòng)更新下載升級(jí)的自我實(shí)現(xiàn)
更新時(shí)間:2007年08月15日 20:13:44 作者:
SmartClient概念近來(lái)比較熱,但在微軟提出這個(gè)名詞以前已經(jīng)有大量的軟件在這么做了,一方面是簡(jiǎn)化客戶端的部署,一方面是提供自動(dòng)升級(jí)的功能;對(duì)于傳統(tǒng)的WinForm應(yīng)用來(lái)講,確實(shí)是可以降低維護(hù)成本的一個(gè)不錯(cuò)的解決方案;
微軟在推出SmartClient概念時(shí),推出了相關(guān)的updater的Application Block,做的也蠻不錯(cuò),但作者前段還是根據(jù)軟件特性自己寫(xiě)了一個(gè)很簡(jiǎn)單的實(shí)現(xiàn),大家也大概能了解一下原理:
筆者的簡(jiǎn)化版自動(dòng)升級(jí)管理器只需要四步走:
1.一個(gè)負(fù)責(zé)查找和下載新版本的本地類
2.本地配置文件中(或在代碼中硬編碼?不太好吧),指向更新服務(wù)器的URL
3.服務(wù)器上一個(gè)標(biāo)識(shí)版本號(hào)和新文件URL的配置文件
4.調(diào)用示例
1.版本管理類
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Net;
using System.IO;
using System.Windows.Forms;
namespace Survey
{
class VersionAgent
{
public static bool CheckNetwork()
{
HttpWebRequest request;
try
{
request = (HttpWebRequest)WebRequest.Create(Pub.GetSetting("UpdateUrl") );//從本地配置文件獲取的網(wǎng)絡(luò)中配置文件的URL
request.Proxy = WebProxy.GetDefaultProxy();
request.GetResponse();//如果可以獲得響應(yīng),說(shuō)明網(wǎng)絡(luò)沒(méi)問(wèn)題
}
catch (Exception e)
{
Pub.logError(e);
return false;
}
return true;
}
public static bool CheckUpdate()
{
XmlDocument doc = loadXMLDocument(Pub.GetSetting("UpdateUrl"));
Sys.UpdateUrl = GetValue(doc, "DownloadURL").Trim();//將來(lái)會(huì)用這個(gè)URL自動(dòng)下載
Sys.UpdatePage = GetValue(doc, "DownloadPage").Trim();//如自動(dòng)下載失敗,會(huì)提供到這個(gè)頁(yè)面手工下載
string warningRate = GetValue(doc, "WarningRate").Trim();
float.TryParse(warningRate,out Sys.WarningRate);
string NetVersion = GetValue(doc, "Version").Trim();
Version LocalVersion=System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
return new Version(NetVersion).CompareTo(new Version(LocalVersion))>0;//大于0說(shuō)明有新版本發(fā)布
}//這個(gè)方法是載入網(wǎng)絡(luò)配置文件,讀取一些不想放在本地的配置參數(shù),以及比較本地和網(wǎng)絡(luò)版本號(hào)
public static bool GoUpdate()
{
return DownLoadFile(Sys.UpdateFile,Sys.UpdateUrl);
}
public static string GetValue(XmlDocument doc, string Key)
{
string Value;
try
{
XmlElement elem = (XmlElement)doc.SelectSingleNode(@"/config/app/" + Key);//讀取配置文件可自行定義
Value = elem == null ? "" : elem.GetAttribute("value");
}
catch
{
Value = "";
}
return Value;
}
public static XmlDocument loadXMLDocument(string FileNameOrUrl)
{
XmlDocument doc = null;
try
{
doc = new XmlDocument();
doc.Load( FileNameOrUrl);
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.Message);
Pub.logError(e);
doc = null;
}
return doc;
}
public static bool DownLoadFile(string FileName, string Url)
{
bool Value = false;
WebResponse response = null;
Stream stream = null;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
response = request.GetResponse();
stream = response.GetResponseStream();
if (!response.ContentType.ToLower().StartsWith("text/"))
{
Value = SaveBinaryFile(response, FileName);
}
}
catch (Exception e)
{
// System.Windows.Forms.MessageBox.Show(e.Message);
Pub.logError(e);
}
return Value;
}
private static bool SaveBinaryFile(WebResponse response, string FileName)
{
bool Value = true;
byte[] buffer = new byte[1024];
try
{
if (File.Exists(FileName))
File.Delete(FileName);
Stream outStream = System.IO.File.Create(FileName);
Stream inStream = response.GetResponseStream();
int l;
do
{
l = inStream.Read(buffer, 0, buffer.Length);
if (l > 0)
outStream.Write(buffer, 0, l);
}
while (l > 0);
outStream.Close();
inStream.Close();
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.Message);
Pub.logError(e);
Value = false;
}
return Value;
}
}
}
2.本地配置文件可能如:
<configuration>
<appSettings>
<add key="UpdateUrl" value="http://www.abc.com/download/release.xml" />
</appSettings>
</configuration>
3.網(wǎng)絡(luò)配置文件可能如:
<config>
<app>
<Version value="1.1.9.2" />
<ReleaseDate value="2006-12-12" />
<DownloadPage value="http://www.abc.com/download/index.htm" />
<DownloadURL value="http://www.abc.com/download/update.exe" />
<WarningRate value="0.3" />
</app>
</config>
4.調(diào)用示例
在認(rèn)為合適的時(shí)機(jī)(比如說(shuō)應(yīng)用程序啟動(dòng)時(shí)),啟動(dòng)一個(gè)后臺(tái)線程去工作:
Thread thread = new Thread(new ThreadStart(threadMethodUpdate));
thread.Start();
private void threadMethodUpdate()
{
if (VersionAgent.CheckNetwork())//網(wǎng)絡(luò)狀況正常
{
if (VersionAgent.CheckUpdate())//檢查更新并獲取網(wǎng)絡(luò)參數(shù)
{
if (VersionAgent.GoUpdate())//獲取新版本(由于我的軟件很小,所以在不提示用戶的情況就進(jìn)行了新版下載,如認(rèn)為不妥,可通過(guò)MessageBox提示一下)
{
MessageBox.Show("檢測(cè)到產(chǎn)品的更新版本,即將開(kāi)始自動(dòng)更新!", "版本升級(jí)", MessageBoxButtons.OK, MessageBoxIcon.Information);
System.Diagnostics.Process.Start(Sys.UpdateFile);
System.Environment.Exit(0);
}
else
{
MessageBox.Show("系統(tǒng)檢測(cè)到更新版本,但自動(dòng)下載失敗,點(diǎn)擊確定進(jìn)行手動(dòng)下載", "版本升級(jí)", MessageBoxButtons.OK, MessageBoxIcon.Error);
System.Diagnostics.Process.Start(Sys.UpdatePage);
System.Environment.Exit(0);
}
}
}
else//也可以什么也不提示
MessageBox.Show("無(wú)法連接到服務(wù)器進(jìn)行自動(dòng)升級(jí)!\n請(qǐng)檢查網(wǎng)絡(luò)連接 " + Pub.GetSetting("UpdateUrl"), "網(wǎng)絡(luò)異常", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
微軟在推出SmartClient概念時(shí),推出了相關(guān)的updater的Application Block,做的也蠻不錯(cuò),但作者前段還是根據(jù)軟件特性自己寫(xiě)了一個(gè)很簡(jiǎn)單的實(shí)現(xiàn),大家也大概能了解一下原理:
筆者的簡(jiǎn)化版自動(dòng)升級(jí)管理器只需要四步走:
1.一個(gè)負(fù)責(zé)查找和下載新版本的本地類
2.本地配置文件中(或在代碼中硬編碼?不太好吧),指向更新服務(wù)器的URL
3.服務(wù)器上一個(gè)標(biāo)識(shí)版本號(hào)和新文件URL的配置文件
4.調(diào)用示例
1.版本管理類
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Net;
using System.IO;
using System.Windows.Forms;
namespace Survey
{
class VersionAgent
{
public static bool CheckNetwork()
{
HttpWebRequest request;
try
{
request = (HttpWebRequest)WebRequest.Create(Pub.GetSetting("UpdateUrl") );//從本地配置文件獲取的網(wǎng)絡(luò)中配置文件的URL
request.Proxy = WebProxy.GetDefaultProxy();
request.GetResponse();//如果可以獲得響應(yīng),說(shuō)明網(wǎng)絡(luò)沒(méi)問(wèn)題
}
catch (Exception e)
{
Pub.logError(e);
return false;
}
return true;
}
public static bool CheckUpdate()
{
XmlDocument doc = loadXMLDocument(Pub.GetSetting("UpdateUrl"));
Sys.UpdateUrl = GetValue(doc, "DownloadURL").Trim();//將來(lái)會(huì)用這個(gè)URL自動(dòng)下載
Sys.UpdatePage = GetValue(doc, "DownloadPage").Trim();//如自動(dòng)下載失敗,會(huì)提供到這個(gè)頁(yè)面手工下載
string warningRate = GetValue(doc, "WarningRate").Trim();
float.TryParse(warningRate,out Sys.WarningRate);
string NetVersion = GetValue(doc, "Version").Trim();
Version LocalVersion=System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
return new Version(NetVersion).CompareTo(new Version(LocalVersion))>0;//大于0說(shuō)明有新版本發(fā)布
}//這個(gè)方法是載入網(wǎng)絡(luò)配置文件,讀取一些不想放在本地的配置參數(shù),以及比較本地和網(wǎng)絡(luò)版本號(hào)
public static bool GoUpdate()
{
return DownLoadFile(Sys.UpdateFile,Sys.UpdateUrl);
}
public static string GetValue(XmlDocument doc, string Key)
{
string Value;
try
{
XmlElement elem = (XmlElement)doc.SelectSingleNode(@"/config/app/" + Key);//讀取配置文件可自行定義
Value = elem == null ? "" : elem.GetAttribute("value");
}
catch
{
Value = "";
}
return Value;
}
public static XmlDocument loadXMLDocument(string FileNameOrUrl)
{
XmlDocument doc = null;
try
{
doc = new XmlDocument();
doc.Load( FileNameOrUrl);
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.Message);
Pub.logError(e);
doc = null;
}
return doc;
}
public static bool DownLoadFile(string FileName, string Url)
{
bool Value = false;
WebResponse response = null;
Stream stream = null;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
response = request.GetResponse();
stream = response.GetResponseStream();
if (!response.ContentType.ToLower().StartsWith("text/"))
{
Value = SaveBinaryFile(response, FileName);
}
}
catch (Exception e)
{
// System.Windows.Forms.MessageBox.Show(e.Message);
Pub.logError(e);
}
return Value;
}
private static bool SaveBinaryFile(WebResponse response, string FileName)
{
bool Value = true;
byte[] buffer = new byte[1024];
try
{
if (File.Exists(FileName))
File.Delete(FileName);
Stream outStream = System.IO.File.Create(FileName);
Stream inStream = response.GetResponseStream();
int l;
do
{
l = inStream.Read(buffer, 0, buffer.Length);
if (l > 0)
outStream.Write(buffer, 0, l);
}
while (l > 0);
outStream.Close();
inStream.Close();
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.Message);
Pub.logError(e);
Value = false;
}
return Value;
}
}
}
2.本地配置文件可能如:
<configuration>
<appSettings>
<add key="UpdateUrl" value="http://www.abc.com/download/release.xml" />
</appSettings>
</configuration>
3.網(wǎng)絡(luò)配置文件可能如:
<config>
<app>
<Version value="1.1.9.2" />
<ReleaseDate value="2006-12-12" />
<DownloadPage value="http://www.abc.com/download/index.htm" />
<DownloadURL value="http://www.abc.com/download/update.exe" />
<WarningRate value="0.3" />
</app>
</config>
4.調(diào)用示例
在認(rèn)為合適的時(shí)機(jī)(比如說(shuō)應(yīng)用程序啟動(dòng)時(shí)),啟動(dòng)一個(gè)后臺(tái)線程去工作:
Thread thread = new Thread(new ThreadStart(threadMethodUpdate));
thread.Start();
private void threadMethodUpdate()
{
if (VersionAgent.CheckNetwork())//網(wǎng)絡(luò)狀況正常
{
if (VersionAgent.CheckUpdate())//檢查更新并獲取網(wǎng)絡(luò)參數(shù)
{
if (VersionAgent.GoUpdate())//獲取新版本(由于我的軟件很小,所以在不提示用戶的情況就進(jìn)行了新版下載,如認(rèn)為不妥,可通過(guò)MessageBox提示一下)
{
MessageBox.Show("檢測(cè)到產(chǎn)品的更新版本,即將開(kāi)始自動(dòng)更新!", "版本升級(jí)", MessageBoxButtons.OK, MessageBoxIcon.Information);
System.Diagnostics.Process.Start(Sys.UpdateFile);
System.Environment.Exit(0);
}
else
{
MessageBox.Show("系統(tǒng)檢測(cè)到更新版本,但自動(dòng)下載失敗,點(diǎn)擊確定進(jìn)行手動(dòng)下載", "版本升級(jí)", MessageBoxButtons.OK, MessageBoxIcon.Error);
System.Diagnostics.Process.Start(Sys.UpdatePage);
System.Environment.Exit(0);
}
}
}
else//也可以什么也不提示
MessageBox.Show("無(wú)法連接到服務(wù)器進(jìn)行自動(dòng)升級(jí)!\n請(qǐng)檢查網(wǎng)絡(luò)連接 " + Pub.GetSetting("UpdateUrl"), "網(wǎng)絡(luò)異常", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
您可能感興趣的文章:
- 用mysql觸發(fā)器自動(dòng)更新memcache的實(shí)現(xiàn)代碼
- asp.net自動(dòng)更新組件分享
- Android 軟件自動(dòng)更新功能實(shí)現(xiàn)的方法
- Mysql查看版本號(hào)的幾種方式
- Android獲取手機(jī)型號(hào)/系統(tǒng)版本號(hào)/App版本號(hào)等信息實(shí)例講解
- MySQL timestamp自動(dòng)更新時(shí)間分享
- 用javascript判斷IE版本號(hào)簡(jiǎn)單實(shí)用且向后兼容
- Python import自定義模塊方法
- php自動(dòng)更新版權(quán)信息顯示的方法
- 使用Appcan客戶端自動(dòng)更新PHP版本號(hào)(全)
相關(guān)文章
輕量級(jí)ORM框架Dapper應(yīng)用之實(shí)現(xiàn)DTO
本文詳細(xì)講解了使用Dapper實(shí)現(xiàn)DTO的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03.NET的DateTime函數(shù)獲取上個(gè)月的起始和截止時(shí)間的方法
這篇文章主要介紹了NET的DateTime函數(shù)獲取上個(gè)月的起始和截止時(shí)間的方法,可廣泛使用于報(bào)表中的時(shí)間自動(dòng)選擇功能,是非常實(shí)用的技巧,需要的朋友可以參考下2015-01-01微信公眾平臺(tái)開(kāi)發(fā)之發(fā)送圖文消息.Net代碼解析
這篇文章主要為大家詳細(xì)解析了微信公眾平臺(tái)開(kāi)發(fā)之發(fā)送圖文消息.Net代碼,感興趣的小伙伴們可以參考一下2016-06-06增加asp.net應(yīng)用程序性能的20種方法(簡(jiǎn)單有效)
增加asp.net應(yīng)用程序性能的20種方法小結(jié),需要的朋友可以參考下,對(duì)于服務(wù)器也需要一些設(shè)置。2010-01-01某個(gè)aspx頁(yè)面突然死了連日志也沒(méi)有的解決方法
某個(gè)aspx頁(yè)面突然死了連日志也沒(méi)有,朋友提醒event viewer里看看,果然錯(cuò)誤在那里,有此情況的朋友可以參考下2013-08-08Asp.net core利用dynamic簡(jiǎn)化數(shù)據(jù)庫(kù)訪問(wèn)
這篇文章介紹了Asp.net core利用dynamic簡(jiǎn)化數(shù)據(jù)庫(kù)訪問(wèn)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07.Net Core簡(jiǎn)單使用Mvc內(nèi)置的Ioc
這篇文章主要為大家詳細(xì)介紹了.Net Core簡(jiǎn)單使用Mvc內(nèi)置的Ioc,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03