Winform使用FTP实现自动更新

2022-07-27 15:12:19

本文实例为大家分享了Winform使用FTP实现自动更新的具体代码,供大家参考,具体内容如下实现思路:在主程序打开前实现判断是否需要更新(可以通过数据库表记录一下版本号或者别的方式记录是否需要更新),...

本文实例为大家分享了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
          {
  www.cppcns.com          //强制关闭进程  
            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

usingjavascript 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>
    /// 服务器密码
    ///javascript </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");

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。