用c# 自动更新程序

作者:冰封一夏
出处:http://www.cnblogs.com/bfyx/
HZHControls官网:http://www.hzhcontrols.com

首先看获取和更新的接口

更新程序Program.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Update
{
  static class Program
  {
    /// <summary>
    /// 更新程序启动后复制自身,使用副本进行更新
    /// -h 不显示界面
    /// -c 不使用copy更新程序
    /// -d 更新完成删除自身,通常用在copy的更新程序
    /// -b 更新下载到备份文件,不替换原文件
    /// -r 更新完成运行的文件,下一个参数为文件路径
    /// -k 如果系统正在运行则干掉
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.ThreadException += Application_ThreadException;

      List<string> lst = args.ToList();
      if (!lst.Contains("-b") && !lst.Contains("-k"))
      {
        //这里判断成程序是否退出
        if (Process.GetProcessesByName("serviceclient").Length > 0)
        {
          MessageBox.Show("服务正在运行,请退出后重试。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
          return;
        }
      }

      if (lst.Contains("-k"))
      {
        var ps = Process.GetProcessesByName("serviceclient");
        if (ps.Length > 0)
        {
          ps[0].Kill();
        }
      }

      //副本更新程序运行
      if (!lst.Contains("-c"))//不存在-c 则进行复制运行
      {
        string strFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), Guid.NewGuid().ToString() + ".exe");
        File.Copy(Application.ExecutablePath, strFile);
        lst.Add("-c");
        lst.Add("-d");
        Process.Start(strFile, string.Join(" ", lst));
      }
      else
      {
        Action actionAfter = null;
        //将更新文件替换到当前目录
        if (!lst.Contains("-b"))
        {
          actionAfter = () =>
          {
            string strUpdatePath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "UpdateCache\\");
            if (Directory.Exists(strUpdatePath) && Directory.GetFiles(strUpdatePath).Length > 0)
            {
              CopyFile(strUpdatePath, System.AppDomain.CurrentDomain.BaseDirectory, strUpdatePath);
              if (File.Exists(Path.Combine(strUpdatePath, "ver.xml")))
                File.Copy(Path.Combine(strUpdatePath, "ver.xml"), Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "ver.xml"), true);
              Directory.Delete(strUpdatePath, true);
            }
          };
        }
        try
        {
          //隐藏运行
          if (!lst.Contains("-h"))
          {
            Application.Run(new FrmUpdate(actionAfter, true));
          }
          else
          {
            FrmUpdate frm = new FrmUpdate(actionAfter);
            frm.Down();
          }
        }
        catch (Exception ex)
        { }
        //运行更新后的文件
        if (lst.Contains("-r"))
        {
          int index = lst.IndexOf("-r");
          if (index + 1 < lst.Count)
          {
            string strFile = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, lst[index + 1]);
            if (File.Exists(strFile))
            {
              Process.Start(strFile, "-u");
            }
          }
        }
        //删除自身
        if (lst.Contains("-d"))
        {
          DeleteItself();
        }
      }
      Application.Exit();
      Process.GetCurrentProcess().Kill();
    }

    private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
    {
      throw new NotImplementedException();
    }
    private static void CopyFile(string strSource, string strTo, string strBasePath)
    {
      string[] files = Directory.GetFiles(strSource);
      foreach (var item in files)
      {
        string strFileName = Path.GetFileName(item).ToLower();

        if (strFileName == "ver.xml ")
        {
          continue;
        }
        //如果是版本文件和文件配置xml则跳过,复制完成后再替换这2个文件
        string strToPath = Path.Combine(strTo, item.Replace(strBasePath, ""));
        var strdir = Path.GetDirectoryName(strToPath);
        if (!Directory.Exists(strdir))
        {
          Directory.CreateDirectory(strdir);
        }
        File.Copy(item, strToPath, true);
      }
      string[] dires = Directory.GetDirectories(strSource);
      foreach (var item in dires)
      {
        CopyFile(item, strTo, strBasePath);
      }
    }

    private static void DeleteItself()
    {
      ProcessStartInfo psi = new ProcessStartInfo("cmd.exe", "/C ping 1.1.1.1 -n 1 -w 1000 > Nul & Del " + Application.ExecutablePath);
      psi.WindowStyle = ProcessWindowStyle.Hidden;
      psi.CreateNoWindow = true;
      Process.Start(psi);
    }
  }
}

更新程序界面

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;

namespace HW.Print.ServiceClient.Update
{
  public partial class FrmUpdate : Form
  {
    private static string m_strkey = "sdfadsfdsfasdf";//定义一个密钥用以验证权限,不适用ticket
    Random r = new Random();
    Action m_actionAfter = null;
    bool m_blnShow = false;
    public FrmUpdate(Action actionAfter, bool blnShow = false)
    {
      m_blnShow = blnShow;
      m_actionAfter = actionAfter;
      InitializeComponent();
    }

    private void Form1_VisibleChanged(object sender, EventArgs e)
    {
      if (Visible)
      {
        var rect = Screen.PrimaryScreen.WorkingArea;
        this.Location = new Point(rect.Right - this.Width, rect.Bottom - this.Height);
      }
    }

    private void FrmUpdate_Load(object sender, EventArgs e)
    {
      Thread th = new Thread(() =>
      {
        Down();
        this.BeginInvoke(new MethodInvoker(delegate ()
        {
          this.Close();
        }));
      });
      th.IsBackground = true;
      th.Start();
    }
    private string CheckIsXP(string strUrl)
    {
      bool blnXp = false;
      if (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 1)
      {
        blnXp = true;
      }
      if (blnXp && strUrl.StartsWith("https"))
      {
        strUrl = "http" + strUrl.Substring(5);
      }
      return strUrl;
    }

    private void SetProcess(string strTitle, int? value, int? maxValue = null)
    {
      this.lblMsg.BeginInvoke(new MethodInvoker(delegate ()
      {
        if (maxValue.HasValue)
        {
          this.progressBar1.Maximum = maxValue.Value;
        }
        if (value.HasValue)
        {
          this.progressBar1.Value = value.Value;
        }
        if (!string.IsNullOrEmpty(strTitle))
        {
          this.lblMsg.Text = strTitle;
        }
        lblValue.Text = this.progressBar1.Value + "/" + this.progressBar1.Maximum;
      }));
    }

    public void Down()
    {
      if (m_blnShow)
        SetProcess("正在检查版本", null);
      try
      {
        //先清理掉旧文件
        try
        {
          if (Directory.Exists(System.AppDomain.CurrentDomain.BaseDirectory + "UpdateCache"))
          {
            Directory.Delete(System.AppDomain.CurrentDomain.BaseDirectory + "UpdateCache", true);
          }
        }
        catch { }
        if (!File.Exists(System.AppDomain.CurrentDomain.BaseDirectory + "setting.dat"))
        {
          Log.WriteLog("配置文件setting.dat不存在!");
          return;
        }
        string strFileUrl = File.ReadAllText(System.AppDomain.CurrentDomain.BaseDirectory + "setting.dat");

        strFileUrl = CheckIsXP(strFileUrl);
        //获取列表文件
        string json = HttpGet(strFileUrl.Trim('/') + "/getUpdaterList?key=" + Encrypt(m_strkey), Encoding.UTF8);
        ResponseMessage rm = fastJSON.JSON.ToObject<ResponseMessage>(json);
        if (rm == null)
        {
          Log.WriteLog("获取更新文件错误");
          return;
        }
        if (!rm.Result)
        {
          Log.WriteLog("获取更新文件错误:" + rm.ErrorMessage);
          return;
        }
        //云列表
        Dictionary<string, DateTime> lstNewFiles = new Dictionary<string, DateTime>();
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(rm.KeyValue);
        var documentElement = doc.DocumentElement;
        var nodes = documentElement.SelectNodes("//files/file");
        foreach (XmlNode item in nodes)
        {
          lstNewFiles[item.InnerText] = DateTime.Parse(item.Attributes["time"].Value);
        }

        List<string> lstUpdateFile = new List<string>();
        string locationXml = System.AppDomain.CurrentDomain.BaseDirectory + "ver.xml";
        if (!File.Exists(locationXml))
        {
          lstUpdateFile = lstNewFiles.Keys.ToList();
        }
        else
        {
          XmlDocument docLocation = new XmlDocument();
          docLocation.Load(locationXml);
          var documentElementLocation = docLocation.DocumentElement;
          var nodesLocation = documentElementLocation.SelectNodes("//files/file");
          foreach (XmlNode item in nodesLocation)
          {
            if (!lstNewFiles.ContainsKey(item.InnerText))
            {
              lstUpdateFile.Add(item.InnerText);
            }
            else if (lstNewFiles[item.InnerText] < DateTime.Parse(item.Attributes["time"].Value))
            {
              lstUpdateFile.Add(item.InnerText);
            }
          }
        }
        if (lstUpdateFile.Count > 0)
        {
          string strRootPath = System.AppDomain.CurrentDomain.BaseDirectory + "UpdateCache";
          if (!System.IO.Directory.Exists(strRootPath))
          {
            System.IO.Directory.CreateDirectory(strRootPath);
          }
          SetProcess("", null, lstUpdateFile.Count);
          for (int i = 0; i < lstUpdateFile.Count; i++)
          {
            if (m_blnShow)
              SetProcess("正在下载:" + lstUpdateFile[i], i + 1);

            string filejson = HttpGet(strFileUrl.Trim('/') + "/downloadUpdaterFile?key=" + Encrypt(m_strkey) + "&file=" + System.Web.HttpUtility.UrlEncode(lstUpdateFile[i]), Encoding.UTF8);
            ResponseMessage filerm = fastJSON.JSON.ToObject<ResponseMessage>(filejson);
            if (rm == null)
            {
              Log.WriteLog("下载更新文件错误");
              return;
            }
            if (!rm.Result)
            {
              Log.WriteLog("下载更新文件错误:" + rm.ErrorMessage);
              return;
            }

            string saveFile = Path.Combine(strRootPath, lstUpdateFile[i]);
            if (!Directory.Exists(Path.GetDirectoryName(saveFile)))
            {
              System.IO.Directory.CreateDirectory(Path.GetDirectoryName(saveFile));
            }
            string strbase64 = filerm.KeyValue;
            MemoryStream stream = new MemoryStream(Convert.FromBase64String(strbase64));
            FileStream fs = new FileStream(strRootPath + "\\" + lstUpdateFile[i], FileMode.OpenOrCreate, FileAccess.Write);
            byte[] b = stream.ToArray();
            fs.Write(b, 0, b.Length);
            fs.Close();

          }

          doc.Save(System.AppDomain.CurrentDomain.BaseDirectory + "UpdateCache//ver.xml");

          if (m_actionAfter != null)
          {
            if (m_blnShow)
              SetProcess("替换文件", null);
            m_actionAfter();
          }

          if (m_blnShow)
            SetProcess("更新完成。", null);
        }
        else
        {
          if (m_blnShow)
            SetProcess("没有需要更新的文件。", null);
        }
      }
      catch (Exception ex)
      {
        if (m_blnShow)
          SetProcess("获取更新列表失败:" + ex.Message, null);
        Log.WriteLog(ex.ToString());
      }
      finally
      {
        if (m_blnShow)
          Thread.Sleep(3000);
      }
    }

    private static string encryptKey = "111222333444555666";

    //默认密钥向量
    private static byte[] Keys = { 0x41, 0x72, 0x65, 0x79, 0x6F, 0x75, 0x6D, 0x79, 0x53, 0x6E, 0x6F, 0x77, 0x6D, 0x61, 0x6E, 0x3F };
    /// <summary>
    /// 加密
    /// </summary>
    /// <param name="encryptString"></param>
    /// <returns></returns>
    public static string Encrypt(string encryptString)
    {
      if (string.IsNullOrEmpty(encryptString))
        return string.Empty;
      RijndaelManaged rijndaelProvider = new RijndaelManaged();
      rijndaelProvider.Key = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 32));
      rijndaelProvider.IV = Keys;
      ICryptoTransform rijndaelEncrypt = rijndaelProvider.CreateEncryptor();

      byte[] inputData = Encoding.UTF8.GetBytes(encryptString);
      byte[] encryptedData = rijndaelEncrypt.TransformFinalBlock(inputData, 0, inputData.Length);

      return System.Web.HttpUtility.UrlEncode(Convert.ToBase64String(encryptedData));
    }
    public static string HttpGet(string url, Encoding encodeing, Hashtable headht = null)
    {
      HttpWebRequest request;

      //如果是发送HTTPS请求
      //if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
      //{
      //ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
      request = WebRequest.Create(url) as HttpWebRequest;
      request.ServicePoint.Expect100Continue = false;
      request.ProtocolVersion = HttpVersion.Version11;
      request.KeepAlive = true;
      //}
      //else
      //{
      //  request = WebRequest.Create(url) as HttpWebRequest;
      //}
      request.Method = "GET";
      //request.ContentType = "application/x-www-form-urlencoded";
      request.Accept = "*/*";
      request.Timeout = 30000;
      request.AllowAutoRedirect = false;
      WebResponse response = null;
      string responseStr = null;
      if (headht != null)
      {
        foreach (DictionaryEntry item in headht)
        {
          request.Headers.Add(item.Key.ToString(), item.Value.ToString());
        }
      }

      try
      {
        response = request.GetResponse();

        if (response != null)
        {
          StreamReader reader = new StreamReader(response.GetResponseStream(), encodeing);
          responseStr = reader.ReadToEnd();
          reader.Close();
        }
      }
      catch (Exception)
      {
        throw;
      }
      return responseStr;
    }
  }
}

定义服务端接口,你可以用任意接口都行,我这里用webapi

获取文件列表

[HttpGet]
    public HttpResponseMessage GetUpdaterList(string key)
    {
      HttpResult httpResult = new HttpResult();
      if (!CheckKey(key))
      {
        httpResult.KeyValue = "";
        httpResult.Result = false;
        httpResult.ErrorMessage = "无权限访问";
      }
      else
      {
        //获取printupdate目录下update.exe的修改日期返回
        string path = Path.Combine(HttpRuntime.AppDomainAppPath, "printupdate");
        StringBuilder strXml = new StringBuilder();
        strXml.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
        strXml.AppendLine("<files>");
        if (Directory.Exists(path))
        {
          string[] fs = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
          var _p = path.ToLower().Trim().Length + 1;
          foreach (var item in fs)
          {
            var dt = File.GetLastAccessTime(item);
            strXml.AppendLine("<file time=\"" + dt.ToString("yyyy-MM-dd HH:mm:ss") + "\">" + item.Substring(_p) + "</file>");
          }
        }
        strXml.AppendLine("</files>");

        httpResult.KeyValue = strXml.ToString();
        httpResult.Result = true;
        httpResult.ErrorMessage = "";
      }
      return new HttpResponseMessage { Content = new StringContent(httpResult.ToJson(), Encoding.GetEncoding("UTF-8"), "application/json") };
    }

定义服务端接口,你可以用任意接口都行,我这里用webapi

获取文件列表

[HttpGet]
    public HttpResponseMessage GetUpdaterList(string key)
    {
      HttpResult httpResult = new HttpResult();
      if (!CheckKey(key))
      {
        httpResult.KeyValue = "";
        httpResult.Result = false;
        httpResult.ErrorMessage = "无权限访问";
      }
      else
      {
        //获取printupdate目录下update.exe的修改日期返回
        string path = Path.Combine(HttpRuntime.AppDomainAppPath, "printupdate");
        StringBuilder strXml = new StringBuilder();
        strXml.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
        strXml.AppendLine("<files>");
        if (Directory.Exists(path))
        {
          string[] fs = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
          var _p = path.ToLower().Trim().Length + 1;
          foreach (var item in fs)
          {
            var dt = File.GetLastAccessTime(item);
            strXml.AppendLine("<file time=\"" + dt.ToString("yyyy-MM-dd HH:mm:ss") + "\">" + item.Substring(_p) + "</file>");
          }
        }
        strXml.AppendLine("</files>");

        httpResult.KeyValue = strXml.ToString();
        httpResult.Result = true;
        httpResult.ErrorMessage = "";
      }
      return new HttpResponseMessage { Content = new StringContent(httpResult.ToJson(), Encoding.GetEncoding("UTF-8"), "application/json") };
    }

下载文件,我这里将文件序列号为base64字符串了,你可以直接返回文件流也行

[HttpGet]
    public HttpResponseMessage DownloadUpdaterFile(string key, string file)
    {
      HttpResult httpResult = new HttpResult();
      if (!CheckKey(key))
      {
        httpResult.KeyValue = "";
        httpResult.Result = false;
        httpResult.ErrorMessage = "无权限访问";
      }
      else
      {
        string path = Path.Combine(HttpRuntime.AppDomainAppPath + "printupdate", file);
        if (!File.Exists(path))
        {
          httpResult.KeyValue = "";
          httpResult.Result = false;
          httpResult.ErrorMessage = "文件不存在";
        }
        else
        {
          httpResult = ConvertToBase64Type(path);
        }
      }
      return new HttpResponseMessage { Content = new StringContent(httpResult.ToJson(), Encoding.GetEncoding("UTF-8"), "application/json") };

    }
HttpResult ConvertToBase64Type(string fileName)
    {
      HttpResult httpResult = new HttpResult();
      var byts = File.ReadAllBytes(fileName);
      httpResult.KeyValue = Convert.ToBase64String(byts);
      return httpResult;
    }
 bool CheckKey(string key)
     {
       return key == Encryption.Encrypt(m_strkey);
     }
private static string encryptKey = "111222333444";

    //默认密钥向量
    private static byte[] Keys = { 0x41, 0x72, 0x65, 0x79, 0x6F, 0x75, 0x6D, 0x79, 0x53, 0x6E, 0x6F, 0x77, 0x6D, 0x61, 0x6E, 0x3F };
    /// <summary>
    /// 加密
    /// </summary>
    /// <param name="encryptString"></param>
    /// <returns></returns>
    public static string Encrypt(string encryptString)
    {
      if (string.IsNullOrEmpty(encryptString))
        return string.Empty;
      RijndaelManaged rijndaelProvider = new RijndaelManaged();
      rijndaelProvider.Key = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 32));
      rijndaelProvider.IV = Keys;
      ICryptoTransform rijndaelEncrypt = rijndaelProvider.CreateEncryptor();

      byte[] inputData = Encoding.UTF8.GetBytes(encryptString);
      byte[] encryptedData = rijndaelEncrypt.TransformFinalBlock(inputData, 0, inputData.Length);

      return Convert.ToBase64String(encryptedData);
    }

需要注意的地方:

1、我这里用到了json,那么不能直接饮用json的dll文件,会出现更新时候占用的问题,可以使用fastjson的开源代码,放进来解决,你可以直接使用xml格式的返回内容,这样就不需要json了,这样更方便

2、如果你的下载接口是返回的文件流,那么你更新程序里面直接接收流保存文件就行了

3、Program.cs里面,停止服务的功能,其实是可以通过传递参数的形式来停止,我这里写死了,你们根据自己需求修改

效果

你可以根据自己的需求,修改下界面效果,这是最简单的示例界面而已。

以上就是用c# 自动更新程序的详细内容,更多关于c# 自动更新程序的资料请关注我们其它相关文章!

(0)

相关推荐

  • C#连接数据库和更新数据库的方法

    对数据库的操作总体可以分为两类:查询(select)和更新(insert,delete,update).为什么这样来分呢?仔细看看两类的区别,select只是从数据库中将数据拿出来使用,而其余三者都会对数据库的物理数据进行修改.这篇文章将接着阐述更新数据. 更新数据库信息首先是连接数据库,对数据库的更新需要一个对象:OleDbCommand.该对象表示要对数据源执行的SQL语句或存储过程. 这个对象有三个属性:1.CommandText表示要设置命令的文本:2.Connection表示要设置命令

  • c#中Winform实现多线程异步更新UI(进度及状态信息)

    引言 在进行Winform程序开发需要进行大量的数据的读写操作的时候,往往会需要一定的时间,然在这个时间段里面,界面ui得不到更新,导致在用户看来界面处于假死的状态,造成了不好的用户体验.所以在大量数据操作的应用上,需要使用多线程来处理这种情况.在c#中使用多线程很方便只需要使用System.Threading.Thread的一个实例的Start方法就行了,但是如何实现多线程之间的交互就不是那么简单.本文实现了用子线程去处理数据,并实时更新主线程的ui状态了.下面就开始一步步的去实现异步线程更新

  • C#微信公众平台开发之access_token的获取存储与更新

    一.什么是access_token? access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token.正常情况下access_token有效期为7200秒,重复获取将导致上次获取的access_token失效.由于获取access_token的api调用次数非常有限,建议开发者全局存储与更新access_token,频繁刷新access_token会导致api调用受限,影响自身业务. 二.要解决的问题 1.如何获取access_token. 2.由于acces

  • c# Winform 程序自动更新实现方法

    Winform程序自动更新我也是第一次做,网上找了自动更新的源码,后来又根据在网上看到的一些方法,自己试了很久,最终还是有写错误,所以花了钱让别人帮忙调试成功的,下面是我自己捣腾出来的,方便大家借鉴,如果有什么错误的地方欢迎指正. 1.由于我是通过服务器的IIS发布自动更新的,更新之前先手动把程序复制到IIS服务器的目录下面,做一些更改,客户端才能正常自动更新.所以第一步是不熟IIS服务器(本人系统windows8): 按照上面的方式,选了之后点确定,系统会自动添加这些内容,然后: 网站建立好了

  • C#如何读取Txt大数据并更新到数据库详解

    环境 Sqlserver 2016 .net 4.5.2 目前测试数据1300万 大约3-4分钟.(限制一次读取条数 和 线程数是 要节省服务器资源,如果调太大服务器其它应用可能就跑不了了), SqlServerDBHelper为数据库帮助类.没有什么特别的处理. 配置连接串时记录把连接池开起来 另外.以下代码中每次写都创建了连接 .之前试过一个连接反复用. 130次大约有20多次 数据库会出问题.并且需要的时间是7-8分钟 左右. 配置文件: xxx.json [ { /*连接字符串 */ "

  • asp.net(c#)程序版本升级更新的实现代码

    直接上代码: 复制代码 代码如下: using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.IO; using System.Net; using System.Xml; namespace Update {     /// <summary>     /// 更新完成触发的事件     /// </summary>     pu

  • C#批量更新sql实例

    本文实例讲述了C#批量更新sql的方法,分享给大家供大家参考.具体方法如下: 要实现批量更新Card数据,主要有以下步骤: 1.首先建立数据库连接 2.把部分数据填充到Dataset中 3.修改Dataset中数据的值 4.更新Dataset 5.循环操作,具体操作过程见下面代码: 复制代码 代码如下: public void BatchUpdate(List<Card> list) {     using (SqlConnection conn = new SqlConnection(DbH

  • C#在子线程中更新窗口部件的写法

    if (textBox1.InvokeRequired) { textBox1.Invoke(new MethodInvoker(delegate { textBox1.AppendText(sb.ToString()); })); }

  • C# Winform 自动更新程序实例详解

    本文实例为大家分享了C# Winform 自动更新程序,供大家参考,具体内容如下 第一步:检查更新 检查更新其实无非就是去比较更新包的版本和本地软件版本,如果高则更新.低则不更新.怎么获取版本号方法很多,本案例是获取软件的配置文件. private bool CheckUpdate() { bool result = false; try { string Cfg = TxtRead(exePath "\\Config.txt"); ConfigLocal = JsonConvert.

  • C# protobuf自动更新cs文件

    网上的教程大都是手动通过protoc编译, 比较难用 给当前工程添加"Google.Protobuf"和"Grpc.Tools"的引用(通过nuget), 然后添加proto文件, 编辑.csproj文件 <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netcoreapp3.1</TargetFramework>

随机推荐