今天閒著沒事,研究了一下在線更新程序版本的問題。也是工作中的需要,開始不知道如何下手,各種百度也沒有找到自己想要的,因為我的需求比較簡單,所以就自己琢磨了一下。講講我的需求吧。自己在IIs上發布了一個網站,這個網站僅僅只是內部使用的,網站的內容就是我的另外一個程序(就叫A程序吧)的打包發布的文件放進去。然後在客戶端啟動我的A程序之前檢查是否有新版本文件發布。如果有,我根據網頁源代碼的信息和本地文件信息進行比較,決定是否下載。如果有下載,下載完成後執行A程序的.exe文件啟動A程序。大致的要求就是這樣。
首先自己發布一個測試網站,也就是簡單的在IIS上將我本機的一個文件夾發布出來,具體怎麼操作就不做講解了。得到我的網址:http://localhost/webTest/。這個網站就作為我以後有新版本文件要發布就直接丟進去。
上面的截圖中有幾個地方需要注明一下:
1.是這個文件最後一次編輯日期。
2.是最後一次編輯時間點。
3.是你這個文件的大小。
4.橢圓部分是一個文件夾。
前面標題說用遞歸,就是因為網站中可能存在子文件夾,遇到子文件夾我就要繼續跟進去讀取源代碼獲取我要的信息。
注:網頁中有個[to parent Directory]這是他的父文件夾,我們在讀取網頁源代碼的時候要對這部分進行處理
注:1,2部分是指這個文件最後一次編輯時間,比如說你在本地有個文件你對他進行最後一次的編輯時間2016/8/26 13:15 那不管你把這個文件拷貝或是上傳到其他地方,那他的編輯時間始終不會變的。
大致的情況介紹的差不多了,接下來直接開始我的讀取網頁下載文件的程序吧!上代碼,一如既往,圖文並茂的文章才是好文章。
一、創建一個winform工程。
圖(1):工程結構
圖(2):winform需要的控件
圖(1)中我添加了兩個幫助類:FileHelper.cs/HttpHelper.cs。在後面做詳細介紹
圖(2)中1是一個label控件,用來顯示正在下載的文件名。2是progressBar控件,winform自帶的進度條控件,我覺得還挺好用的。。還需要一個backgroundwork控件
二:幫助類文件
FileHelper.cs幫助類文件。
1 public class FileHelper 2 { 3 public DateTime ModiDate { get; set; } //最後編輯時間 4 5 public long Size { get; set; } //文件大小 6 7 public String FilePath { get; set; } //路徑+文件名 8 } View CodeHttpHelper.cs
1 /// <summary> 2 /// 獲取網頁源代碼 3 /// </summary> 4 /// <param name="serverUrl">網址</param> 5 /// <param name="listFile">存放下載文件的集合</param> 6 /// <param name="listHref">存放子目錄集合</param> 7 8 public static void GetHtmlResource(string serverUrl, List<FileHelper> listFile, List<string> listHref) 9 { 10 #region 11 //Uri u = new Uri(serverUrl); 12 //string host = u.Host; 13 //if (serverUrl.EndsWith("/")) 14 //{ 15 // //1.獲取網頁源代碼 16 // WebClient wc = new WebClient(); 17 // wc.Credentials = CredentialCache.DefaultCredentials; 18 // byte[] htmlData = wc.DownloadData(serverUrl); 19 // string htmlStr = Encoding.Default.GetString(htmlData); 20 // //2.正則找到href屬性內容截取 21 // string regMat = @"(?is)<a[^>]*?href=(['""\s]?)(?<href>[^'""\s]*)\1[^>]*?"; 22 // MatchCollection mat = Regex.Matches(htmlStr, regMat, RegexOptions.IgnoreCase); 23 // List<string> listHref = new List<string>(); //存放href結合 24 // for (int i = 0; i < mat.Count; i++) 25 // { 26 // string item = mat[i].Groups["href"].Value; 27 // listHref.Add(item); 28 // MatchCollection match = Regex.Matches(htmlStr, "([0-9]{1,})\\s\\<A\\sHREF=\""+ item+"\"", RegexOptions.IgnoreCase); 29 // if(match.Count == 1 && match[0].Groups.Count==2) 30 // { 31 // fileSize.Add(@"http://" + host + item, int.Parse(match[0].Groups[1].Value)); 32 // } 33 // } 34 // foreach (var item in listHref) //Match item in mat 35 // { 36 // string url = @"http://"+host + item; 37 // if (serverUrl.StartsWith(url)) 38 // { 39 // continue; 40 // } 41 // GetHtmlResource(url, serverFilePath,fileSize); 42 // } 43 //} 44 //else 45 //{ 46 // serverFilePath.Add(serverUrl); 47 //} 48 #endregion 49 50 Uri u = new Uri(serverUrl); 51 string host = u.Host; 52 if (serverUrl.EndsWith("/")) 53 { 54 //1.獲取網頁源代碼 55 WebClient wc = new WebClient(); 56 wc.Credentials = CredentialCache.DefaultCredentials; 57 byte[] htmlData = wc.DownloadData(serverUrl); 58 string htmlTempStr = Encoding.Default.GetString(htmlData); 59 //完全用字符串截取的方式得到自己想要的東西 60 htmlTempStr = htmlTempStr.Substring(htmlTempStr.IndexOf("<pre>")); 61 htmlTempStr = htmlTempStr.Substring(0, htmlTempStr.IndexOf("</pre>")); 62 htmlTempStr = htmlTempStr.Replace("<pre>", ""); 63 htmlTempStr = htmlTempStr.Replace("</pre>", ""); 64 htmlTempStr = htmlTempStr.Replace("<dir>", "-1"); //把子菜單前面的"<dir&"改為-1,為了跟其他的信息一致有規律 65 htmlTempStr = htmlTempStr.Replace("<br>", "#"); 66 string[] tempStr = htmlTempStr.Split('#'); 67 ArrayList listStr = new ArrayList(tempStr); 68 //移除每個新網頁的父級文件夾 69 listStr.RemoveAt(0); 70 for (int i = 0; i < listStr.Count; i++) 71 { 72 if (String.IsNullOrWhiteSpace(listStr[i].ToString())) 73 { 74 listStr.RemoveAt(i); 75 } 76 } 77 tempStr = (string[])listStr.ToArray(typeof(string)); 78 79 for (int f = 0; f < tempStr.Length; f++) 80 { 81 //截取最後修改日期帶時間 82 string fileModiTime = tempStr[f].Substring(0, 20); 83 //截取文件大小 84 string fileSize = tempStr[f].Substring(20, tempStr[f].IndexOf("<A") - 20); 85 //截取文件路徑 86 string filePath = tempStr[f].Split('\"')[1]; 87 FileHelper file = new FileHelper(); 88 file.ModiDate = Convert.ToDateTime(fileModiTime.Trim()); 89 file.Size = Convert.ToInt32(fileSize.Trim()); 90 file.FilePath = @"http://" + host + filePath; 91 //如果大小為-1,我就認為是子文件夾,添加到集合中 92 if (file.Size == -1) 93 { 94 listHref.Add(file.FilePath); 95 } 96 else 97 { 98 //添加到要下載的文件集合中 99 listFile.Add(file); 100 } 101 } 102 //循環我的子文件夾集合 103 foreach (var item in listHref) 104 { 105 //如果item等於我的serverUrl繼續 106 if (serverUrl.StartsWith(item)) 107 { 108 continue; 109 } 110 //遞歸 111 GetHtmlResource(item, listFile, listHref); 112 } 113 114 } 115 } View Code 1 /// <summary> 2 /// 下載文件 3 /// </summary> 4 /// <param name="serverUrl">文件在服務器的全路徑</param> 5 /// <param name="localFilePath">下載到本地的路徑</param> 6 public static void DownLoadMdiFile(string serverUrl,string localFilePath) 7 { 8 //localFilePath = localFilePath.Replace(".exe.config.xml", ".exe.config"); 9 if (localFilePath.Contains(".exe.config.xml")) 10 { 11 localFilePath = localFilePath.Replace(".exe.config.xml", ".exe.config"); 12 } 13 if (localFilePath.Contains(".config.xml")) 14 { 15 localFilePath = localFilePath.Replace(".config.xml", ".config"); 16 } 17 //網頁中子文件夾是否存在,如果不存在,創建文件夾,存在直接下載文件 18 FileInfo file = new FileInfo(localFilePath); 19 if(!file.Directory.Exists) 20 { 21 Directory.CreateDirectory(file.Directory.FullName); 22 23 } 24 try 25 { 26 WebClient wc = new WebClient(); 27 if (!localFilePath.Contains("web.config")) 28 { 29 wc.DownloadFile(serverUrl, localFilePath); 30 } 31 } 32 catch (Exception e) 33 { 34 throw; 35 } 36 } View Code三:banckgroundwork控件
對於這個控件我需要實現他的三個事件。很簡單的三個事件,看事件名稱就能知道他的意思了
第一個:backgroundWorker1_DoWork
1 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 2 { 3 #region 4 //string installUrl = GetInstallPath(); 5 //List<string> listFilePath = new List<string>(); 6 //Dictionary<string, int> fileSize = new Dictionary<string, int>(); 7 //HttpHelper.GetHtmlResource(installUrl, listFilePath, fileSize); 8 //for (int i=0;i<listFilePath.Count;i++) 9 //{ 10 // if (backgroundWorker1.CancellationPending) 11 // { 12 // e.Cancel = true; 13 // return; 14 // } 15 // double total = listFilePath.Count; 16 // double current = i+1; 17 // int progress = (int)(current / total * 100); 18 // string serverUrl = listFilePath[i]; 19 // int size = fileSize[serverUrl]; 20 // backgroundWorker1.ReportProgress(progress, serverUrl.Replace(installUrl, "")); 21 // string localPath = serverUrl.Replace(installUrl, localInstallPath); 22 // if (File.Exists(localPath)) 23 // { 24 // FileStream fs = new FileStream(localPath, FileMode.Open); 25 26 // if (fs.Length != size) 27 // { 28 // try 29 // { 30 // HttpHelper.DownLoadMdiFile(serverUrl, localPath); 31 // } 32 // catch (Exception ) 33 // { 34 // throw; 35 // } 36 // } 37 // fs.Close(); 38 // } 39 // else 40 // { 41 // HttpHelper.DownLoadMdiFile(serverUrl, localPath); 42 // } 43 //} 44 #endregion 45 string installUrl = GetInstallPath(); 46 List<string> listHref = new List<string>();//存放子文件夾集合 47 List<FileHelper> listFile = new List<FileHelper>();//存放下載文件集合 48 HttpHelper.GetHtmlResource(installUrl, listFile, listHref); 49 for (int i = 0; i < listFile.Count; i++) 50 { 51 if (backgroundWorker1.CancellationPending) 52 { 53 e.Cancel = true; 54 return; 55 } 56 double total = listFile.Count; 57 double current = i + 1; 58 int progress = (int)(current / total * 100); 59 //服務器文件+全路徑 60 string serverUrl = listFile[i].FilePath; 61 //服務器文件大小 62 long size = listFile[i].Size; 63 //服務器文件最後修改時間 64 DateTime modiTine = listFile[i].ModiDate; 65 //backgroundWorker1執行到那個階段 66 backgroundWorker1.ReportProgress(progress, serverUrl.Replace(installUrl, "")); 67 string localPath = serverUrl.Replace(installUrl, localInstallPath); 68 //判斷文件是否存在 69 if (File.Exists(localPath)) 70 { 71 //獲取本地文件 72 FileInfo fs = new FileInfo(localPath); 73 //如果服務器文件大小,最後修改時間和本地文件進行對比,是否有變化 74 if (fs.Length != size || fs.LastWriteTime != modiTine) 75 { 76 77 try 78 { 79 HttpHelper.DownLoadMdiFile(serverUrl, localPath); 80 } 81 catch (Exception) 82 { 83 84 throw; 85 } 86 } 87 88 } 89 else 90 { 91 HttpHelper.DownLoadMdiFile(serverUrl, localPath); 92 } 93 } 94 } View Code第二個:backgroundWorker1_ProgressChanged
1 private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 2 { 3 this.progressBar.Value = e.ProgressPercentage; 4 var display = e.UserState.ToString(); 5 labDisplay.Text = display.Trim(); 6 //lbl_pbvalue.Text = "更新進度" + e.ProgressPercentage + "%"; 7 } View Code第三個:backgroundWorker1_RunWorkerCompleted
1 private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 2 { 3 runningPath += "A.exe"; 4 try 5 { 6 System.Diagnostics.Process.Start(runningPath); 7 } 8 catch (Exception ex) 9 { 10 MessageBox.Show(ex.Message); 11 } 12 13 this.Close(); 14 } View Code在使用backgroundwork和progressBar控件的時候需要注意幾個點
this.backgroundWorker1.WorkerReportsProgress = true; 用於進度條更新
this.backgroundWorker1.WorkerSupportsCancellation = true; 提供中途終止進程
this.progressBar.Maximum = 100;給一個最大值
好吧!就這樣一個簡單的在線更新文件的程序就搞定啦!
【轉載注明出處!謝謝】