首頁 > 軟體

Winform使用FTP實現自動更新

2022-07-27 18:00:24

本文範例為大家分享了Winform使用FTP實現自動更新的具體程式碼,供大家參考,具體內容如下

實現思路:在主程式開啟前實現判斷是否需要更新(可以通過資料庫表記錄一下版本號或者別的方式記錄是否需要更新),若需要更新時從ftp站點下載更新包(關於設定ftp站點自己可以搜這裡不再做詳述)。自己可以制定字尾格式的包或者別的!一般用壓縮包的形式來存放最新程式,將檔案下載到本地路徑,在關閉當前程式開啟更新程式做解壓替換檔案操作,或者可以用批次處理文、可執行檔案來做操作都行!

1.判斷是否有新版本。

2.通過ftp將更新包下載至本地路徑。

3.開啟更新程式(批次檔或可執行檔案)同時關閉所有主程式程序。

4.在更新程式中進行解壓、替換操作。

5.待替換完畢刪除本地更新包(可選)。

6.開啟新程式同時關閉所有更新程式程序。

程式碼:

1.在程式入口處Program.cs中做判斷:

//判斷版本號是否為資料庫表的版本號
  if (edition == "2021.5.12.0.1")//版本號自己可以判斷
            {
                var resulta = MessageBox.Show("有可用更新,是否更新?", "系統提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (resulta == DialogResult.No)
                {
                    Application.Run(new Form1());
                    return;
                }
               
                //從伺服器獲取新壓縮檔案後下載至某一路徑
                UpdatateHelp help = new UpdatateHelp();//更新類
                help.IP = "xxx.xx.xx.xxx";
                help.ServerFile = "OldDemoUpd.zip";
                help.User = "Administrator";
                help.Password = "*****";
                string message = string.Empty;
                if (!help.DownloadFile(out message))
                {
                    var result = MessageBox.Show(message, "系統提示", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                    if (result == DialogResult.Yes)
                    {
                        Application.Run(new Form1());
                        return;
                    }
                    else
                    {
                        //強制關閉程序    
                        var proc = System.Diagnostics.Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
                        foreach (Process item in proc)
                        {
                            item.Kill();
                        }
                    }
                }
                //替換程式檔案(用一個update程式負責解壓程式並替換檔案,在刪除壓縮檔案)
                System.Diagnostics.Process.Start(Application.StartupPath + "\Update\" + "AutoUpdate.exe");
                //關閉當前程序   
                foreach (Process item in System.Diagnostics.Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName))
                {
                    item.Kill();
                }
            }

2.更新幫助類UpdatateHelp

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;

namespace OldDemo
{
    class UpdatateHelp
    {
        /// <summary>
        /// 伺服器IP
        /// </summary>
        public string IP { get; set; }
        /// <summary>
        /// 伺服器檔案和下載到本地檔名一致
        /// </summary>
        public string ServerFile { get; set; }
        /// <summary>
        /// 伺服器使用者名稱
        /// </summary>
        public string User { get; set; }
        /// <summary>
        /// 伺服器密碼
        /// </summary>
        public string Password { get; set; }
        /// <summary>
        /// 下載伺服器檔案
        /// </summary>
        /// <param name="Message">返回資訊</param>
        /// <returns></returns>
        public bool DownloadFile(out string Message)
        {
            FtpWebRequest reqFTP;
            try
            {
                FileStream outputStream = new FileStream(Path.GetTempPath()+ ServerFile, FileMode.Create);//本地快取目錄
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + IP + "//"+ ServerFile));
                reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;//指定當前請求是什麼命令(upload,download,filelist等)
                reqFTP.UseBinary = true;//指定檔案傳輸的型別
                reqFTP.Credentials = new NetworkCredential(User, Password); //指定登入ftp伺服器的使用者名稱和密碼。
                reqFTP.KeepAlive = false;//指定在請求完成之後是否關閉到 FTP 伺服器的控制連線
                //reqFTP.UsePassive = true;//指定使用主動模式還是被動模式
                //reqFTP.Proxy = null;//設定不使用代理
                //reqFTP.Timeout = 3000;
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                Stream ftpStream = response.GetResponseStream();
                long cl = response.ContentLength;
                int bufferSize = 2048;
                int readCount;
                byte[] buffer = new byte[bufferSize];
                readCount = ftpStream.Read(buffer, 0, bufferSize);
                while (readCount > 0)
                {
                    outputStream.Write(buffer, 0, readCount);
                    readCount = ftpStream.Read(buffer, 0, bufferSize);
                }
                ftpStream.Close();
                outputStream.Close();
                response.Close();
                Message = "下載更新檔案成功!";
                return true;
            }
            catch (Exception ex)
            {
                Message = "下載更新檔案失敗!原因:"+ex.Message + " 按是進入原程式,按否關閉程式!";
                return false;
            }
           
        }
    }
}

3.關閉主程式程序開啟更新程式AutoUpdate.exe,可以在Program中執行也可以在程式中新建一個表單顯示進度條等!此處用Form1表單來做解壓處理,需要注意的地方是我參照了using Ionic.Zip;可以在Nuget下搜一下DotNetZip,該dll是針對檔案解壓縮幫助類,此只是例舉解壓,有興趣自己研究別的實現!

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Ionic.Zip;

namespace AutoUpdate
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();  
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            StartUpdate();
        }
        void StartUpdate()
        {
            string FileLoad = System.IO.Path.GetTempPath() + "OldDemoUpd.zip";
            string IndexLoad = Application.StartupPath + "\";
            var lis = IndexLoad.Split('\').ToList();
            lis.Remove("");
            lis.Remove("Update");//由於更新程式沒和主程式目錄同步,所以需要返回到Update資料夾上一級主程式目錄中。
            IndexLoad = string.Join("\",lis);
            //1.解壓臨時檔案包到當前路徑並刪除壓縮包
            if (System.IO.File.Exists(FileLoad))
            {
                label1.Text = "正在解壓軟體更新包...";
                //存在就解壓
                if (!Decompression(FileLoad, IndexLoad, true))
                {
                    MessageBox.Show("解壓更新包失敗,請重試!", "系統提示");
                    //關閉當前程序   
                    foreach (System.Diagnostics.Process item in System.Diagnostics.Process.GetProcessesByName(System.Diagnostics.Process.GetCurrentProcess().ProcessName))
                    {
                        item.Kill();
                    }
                }
                label1.Text = "正在刪除軟體更新包...";
                //刪除壓縮包
                System.IO.File.Delete(FileLoad);
            }
            else
            {
                MessageBox.Show("軟體更新包不存在,請重新開啟程式以獲取更新包!", "系統提示");
                //關閉當前程序   
                foreach (System.Diagnostics.Process item in System.Diagnostics.Process.GetProcessesByName(System.Diagnostics.Process.GetCurrentProcess().ProcessName))
                {
                    item.Kill();
                }
            }
            label1.Text = "更新成功,請稍後...";
            //2.開啟更新後程式
            System.Diagnostics.Process.Start(IndexLoad + "\" + "OldDemo.exe");
            //關閉當前程序   
            foreach (System.Diagnostics.Process item in System.Diagnostics.Process.GetProcessesByName(System.Diagnostics.Process.GetCurrentProcess().ProcessName))
            {
                item.Kill();
            }
        }

        /// <summary>
        /// 解壓ZIP檔案
        /// </summary>
        /// <param name="strZipPath">待解壓的ZIP檔案</param>
        /// <param name="strUnZipPath">解壓的目錄</param>
        /// <param name="overWrite">是否覆蓋</param>
        /// <returns>成功:true/失敗:false</returns>
        public static bool Decompression(string strZipPath, string strUnZipPath, bool overWrite)
        {
            try
            {
                ReadOptions options = new ReadOptions();
                options.Encoding = Encoding.Default;//設定編碼,解決解壓檔案時中文亂碼
                using (ZipFile zip = ZipFile.Read(strZipPath, options))
                {
                    foreach (ZipEntry entry in zip)
                    {
                        if (string.IsNullOrEmpty(strUnZipPath))
                        {
                            strUnZipPath = strZipPath.Split('.').First();
                        }
                        if (overWrite)
                        {
                            entry.Extract(strUnZipPath, ExtractExistingFileAction.OverwriteSilently);//解壓檔案,如果已存在就覆蓋
                        }
                        else
                        {
                            entry.Extract(strUnZipPath, ExtractExistingFileAction.DoNotOverwrite);//解壓檔案,如果已存在不覆蓋
                        }
                    }
                    return true;
                }
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}

4.需要注意的幾個地方有:

4.1在主程式的生成目錄下建立一個資料夾Update;

4.2把更新程式的生成檔案放入Update資料夾下邊,主要是主程式Program中這一段(主程式目錄和更新目錄不是同級):

//替換程式檔案(用一個update程式負責解壓程式並替換檔案,在刪除壓縮檔案)
 System.Diagnostics.Process.Start(Application.StartupPath + "\Update\" + "AutoUpdate.exe");

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com