文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

使用c#怎么自动更新程序

2023-06-14 06:31

关注

使用c#怎么自动更新程序?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

主要功能介绍

实现文件的自动更新。主要功能:

  1. 支持整包完全更新,即客户端只需输入一个服务器地址,即可下载所有文件。

  2. 支持增量更新,即只更新指定的某几个文件。

  3. 支持自动更新程序的更新

更新界面如图:

使用c#怎么自动更新程序

客户端

main方法入口

/// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() {  //在主程序中 更新替换自动升级程序  //ReplaceAutoUpgrade();  bool isEnterMain = false;  try  {  //设置默认更新地址,如果不设置,后面会从配置文件,或界面上进行设置  UpgradeHelper.Instance.DefaultUrl = "http://localhost:17580";  if (UpgradeHelper.Instance.Local_UpgradeModel != null)  {   UpgradeHelper.Instance.UpgradeUrl = UpgradeHelper.Instance.Local_UpgradeModel.UpgradeUrl;  }  if (UpgradeHelper.Instance.WillUpgrades.Count == 0 && UpgradeHelper.Instance.Local_UpgradeModel != null)  {   //没有待更新,并且本地版本信息文件不为空,则直接启动主程序   bool isSucced = UpgradeHelper.StartRunMain(UpgradeHelper.Instance.Local_UpgradeModel.RunMain);   if (isSucced)   {   Application.Exit();   }   else   {   //清理版本信息 以便重新检测版本   UpgradeHelper.Instance.ClearUpgradeModel();   isEnterMain = true;   }  }  else  {   isEnterMain = true;  }  }  catch (Exception ex)  {  isEnterMain = true;  MessageBox.Show("运行更新程序异常:\n" + ex.Message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);  }  if (isEnterMain)  {  //进入更新主界面  Application.EnableVisualStyles();  Application.SetCompatibleTextRenderingDefault(false);  Application.Run(new FrmUpdate());  } }

主窗体代码

public partial class FrmUpdate: Form{ /// <summary> /// 构造函数 /// </summary> /// <param name="tempPath"></param> /// <param name="updateFiles"></param> public FrmUpdate() {  InitializeComponent(); } /// <summary> /// 窗体加载事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void FrmUpdate_Load(object sender, EventArgs e) {  try  {  //加载服务器地址  txtHostUrl.Text = UpgradeHelper.Instance.UpgradeUrl;  BeginUpgrade();  }  catch(Exception ex)  {  Output("初始化异常:" + ex.Message);  } } /// <summary> /// 手动更新 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void butBegin_Click(object sender, EventArgs e) { try {  if(string.IsNullOrWhiteSpace(txtHostUrl.Text))  {  Output("请先输入服务器地址!");  return;  }  UpgradeHelper.Instance.UpgradeUrl = txtHostUrl.Text.Trim();  //清理版本信息 以便重新检测版本  UpgradeHelper.Instance.ClearUpgradeModel();  BeginUpgrade(); } catch(Exception ex) {  Output("更新异常:" + ex.Message); } } private void BeginUpgrade() {  try  {  if(string.IsNullOrWhiteSpace(UpgradeHelper.Instance.UpgradeUrl))  {   return;  }  if(!(UpgradeHelper.Instance.UpgradeUrl.StartsWith("http://") || UpgradeHelper.Instance.UpgradeUrl.StartsWith("https://")))  {   Output("错误的服务器地址,地址必须以http://或者https://开头");   return;  }  //判断是否有更新  if(UpgradeHelper.Instance.WillUpgrades.Count > 0 && UpgradeHelper.Instance.Server_UpgradeModel != null)  {   SetWinControl(false);   //杀死主进程   UpgradeHelper.KillProcess(UpgradeHelper.Instance.Server_UpgradeModel.RunMain);   RunUpgrade(); //启动更新  }  }  catch(Exception ex)  {  Output("更新异常:" + ex.Message);  } } /// <summary> /// 启动更新 /// </summary> private void RunUpgrade() {  //启动更新  SetCaption(string.Format("共需更新文件{0}个,已更新0个。正在更新下列文件:", UpgradeHelper.Instance.WillUpgrades.Count));  Task.Factory.StartNew(() =>  {  string curFile = "";  try  {   int idx = 0;   foreach(KeyValuePair < string, string > item in UpgradeHelper.Instance.WillUpgrades)   {    curFile = item.Key;    string filePath = string.Format("{0}\\{1}", Application.StartupPath, item.Key);    if(item.Key.IndexOf(UpgradeHelper.Instance.Server_UpgradeModel.AutoUpgrade) >= 0)    {    //如果当前文件为更新主程序    filePath = string.Format("{0}\\AutoUpgradeTemp\\{1}", Application.StartupPath, item.Key);    }    string directory = Path.GetDirectoryName(filePath);    if(!Directory.Exists(directory))    {    Directory.CreateDirectory(directory);    }    MyWebResquest.DownloadFile(UpgradeHelper.Instance.UpgradeUrl, item.Key, filePath);    idx++;    SetCaption(string.Format("共需更新文件{0}个,已更新{1}个。更新文件列表:", UpgradeHelper.Instance.WillUpgrades.Count, idx));    Output(string.Format("更新文件{0}完成", curFile));   }   //保存版本文件   File.WriteAllText(UpgradeHelper.Instance.Local_UpgradeXmlPath, UpgradeHelper.Instance.Server_UpgradeXml);   SetCaption(string.Format("更新完成,共更新文件{0}个", UpgradeHelper.Instance.WillUpgrades.Count));   Output(string.Format("更新完成,共更新文件{0}个", UpgradeHelper.Instance.WillUpgrades.Count));   //下载完成后处理   UpgradeHelper.StartRunMain(UpgradeHelper.Instance.Server_UpgradeModel.RunMain);   //退出当前程序   ExitCurrent();  }  catch(Exception ex)  {   Output(string.Format("更新文件{0}异常:{1}", curFile, ex.Message));   SetWinControl(true);  }  }); } /// <summary> /// 设置界面控件是否可用 /// </summary> /// <param name="enabled"></param> private void SetWinControl(bool enabled) {  if(this.InvokeRequired)  {  Action < bool > d = new Action < bool > (SetWinControl);  this.Invoke(d, enabled);  }  else  {  txtHostUrl.Enabled = enabled;  butBegin.Enabled = enabled;  } } /// <summary> /// 退出当前程序 /// </summary> private void ExitCurrent() { if(this.InvokeRequired) {  Action d = new Action(ExitCurrent);  this.Invoke(d); } else {  Application.Exit(); } }# region 日志输出 /// <summary> /// 设置跟踪状态 /// </summary> /// <param name="caption"></param> private void SetCaption(string caption) {  if(this.lblCaption.InvokeRequired)  {  Action < string > d = new Action < string > (SetCaption);  this.Invoke(d, caption);  }  else  {  this.lblCaption.Text = caption;  } } /// <summary> /// 设置跟踪状态 /// </summary> /// <param name="caption"></param> private void Output(string log) { if(this.txtLog.InvokeRequired) {  Action < string > d = new Action < string > (Output);  this.Invoke(d, log); } else {  txtLog.AppendText(string.Format("{0}:{1}\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), log));  txtLog.ScrollToCaret(); } } private void ClearOutput() { if(this.txtLog.InvokeRequired) {  Action d = new Action(ClearOutput);  this.Invoke(d); } else {  txtLog.Text = ""; } }# endregion private void FrmUpdate_FormClosing(object sender, FormClosingEventArgs e) { if(e.CloseReason == CloseReason.UserClosing) {  if(MessageBox.Show("升级未完成,退出后将导致软件无法正常使用,你确定要退出吗?", "退出提示", MessageBoxButtons.YesNo) != System.Windows.Forms.DialogResult.Yes)  {  //取消"关闭窗口"事件  e.Cancel = true;  } } }}

更新帮助类

/// <summary>/// 更新帮助类/// </summary>public class UpgradeHelper{ /// <summary> /// 默认服务器地址 /// 在配置文件中未找到地址时,使用此地址进行更新 /// </summary> public string DefaultUrl { get; set; } public string _upgradeUrl; /// <summary> /// 获取或设置服务器地址 /// </summary> public string UpgradeUrl { get {  if(string.IsNullOrWhiteSpace(_upgradeUrl))  {  return DefaultUrl;  }  return _upgradeUrl; } set {  _upgradeUrl = value; } } /// <summary> /// 本地配置文件路径 /// </summary> public string Local_UpgradeXmlPath = Path.Combine(Application.StartupPath, "UpgradeList.xml"); private UpgradeModel _local_UpgradeModel; /// <summary> /// 本地版本信息 /// </summary> public UpgradeModel Local_UpgradeModel { get {  try  {  if(_local_UpgradeModel == null)  {   if(File.Exists(Local_UpgradeXmlPath))   {   _local_UpgradeModel = new UpgradeModel();   _local_UpgradeModel.LoadUpgrade(File.ReadAllText(Local_UpgradeXmlPath));   }  }  return _local_UpgradeModel;  }  catch(Exception ex)  {  throw new Exception(string.Format("获取本地版本文件UpgradeList.xml异常:{0}", ex.Message));  } } } private UpgradeModel _server_UpgradeModel; /// <summary> /// 服务器版本信息 /// </summary> public UpgradeModel Server_UpgradeModel { get {  try  {  if(_server_UpgradeModel == null && !string.IsNullOrWhiteSpace(UpgradeUrl))  {   string resXml = MyWebResquest.GetUpgradeList(UpgradeUrl);   if(!string.IsNullOrWhiteSpace(resXml))   {   _server_UpgradeModel = new UpgradeModel();   _server_UpgradeModel.LoadUpgrade(resXml);   _server_UpgradeXml = resXml;   }  }  return _server_UpgradeModel;  }  catch(Exception ex)  {  throw new Exception(string.Format("获取服务端版本文件UpgradeList.xml异常:{0}", ex.Message));  } } } private string _server_UpgradeXml; /// <summary> /// 服务端版本配置xml /// </summary> public string Server_UpgradeXml { get {  return _server_UpgradeXml; } } private Dictionary < string, string > _willUpgrades; /// <summary> /// 待更新文件列表,如果为0,则表示不需要更新 /// </summary> public Dictionary < string, string > WillUpgrades {  get  {  if(_willUpgrades == null)  {   _willUpgrades = new Dictionary < string, string > ();   //如果服务器端未获取到版本信息 则不更新   if(Server_UpgradeModel != null)   {   if(Local_UpgradeModel == null) //本地版本信息为空 全部更新   {    _willUpgrades = Server_UpgradeModel.DictFiles;   }   else   {    //对比需要更新的文件    foreach(var item in Server_UpgradeModel.DictFiles)    {    //如果找到    if(Local_UpgradeModel.DictFiles.ContainsKey(item.Key))    {     //如果版本不匹配     if(Local_UpgradeModel.DictFiles[item.Key] != item.Value)     {     _willUpgrades.Add(item.Key, item.Value);     }    }    else    {     //没有找到     _willUpgrades.Add(item.Key, item.Value);    }    }   }   }  }  return _willUpgrades;  } } /// <summary> /// 清空版本信息 /// </summary> public void ClearUpgradeModel() { if(File.Exists(Local_UpgradeXmlPath)) {  try  {  string xmlStr = File.ReadAllText(Local_UpgradeXmlPath);  XmlDocument xmlDoc = new XmlDocument();  xmlDoc.LoadXml(xmlStr);  XmlNode node = xmlDoc.SelectSingleNode("Upgrade/Files");  if(node != null && node.ChildNodes.Count > 0)  {   node.RemoveAll();  }  File.WriteAllText(UpgradeHelper.Instance.Local_UpgradeXmlPath, xmlDoc.InnerXml);  }  catch(Exception)  {} } _local_UpgradeModel = null; _server_UpgradeModel = null; _willUpgrades = null; }# region 单例对象 private static UpgradeHelper _instance; /// <summary> /// 单例对象 /// </summary> public static UpgradeHelper Instance { get {  if(_instance == null)  {  _instance = new UpgradeHelper();  //初始化本地配置文件,以及服务器地址  if(_instance.Local_UpgradeModel != null)  {   _instance.UpgradeUrl = _instance.Local_UpgradeModel.UpgradeUrl;  }  }  return _instance; } }# endregion# region 静态方法 /// <summary> /// 启动主程序 /// </summary> /// <param name="fileName"></param> public static bool StartRunMain(string fileName) {  string fullPath = fileName;  try  {  Process process = GetProcess(fileName);  if(process != null) //以及存在运行中的主进程  {   return true;  }  fullPath = string.Format("{0}\\{1}", Application.StartupPath, fileName);  ProcessStartInfo main = new ProcessStartInfo(fullPath);  Process.Start(fullPath);  return true;  }  catch(Exception ex)  {  MessageBox.Show(string.Format("主程序{0}调用失败:\n{1}", fullPath, ex.Message), "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);  }  return false; } /// <summary> /// 杀死进程 /// </summary> /// <param name="process"></param> public static void KillProcess(string processName) {  if(string.IsNullOrWhiteSpace(processName)) return;  processName = processName.ToLower();  processName = processName.Replace(".exe", "");  //杀死主进程  Process[] processes = Process.GetProcesses();  foreach(Process process in processes)  {  if(!string.IsNullOrWhiteSpace(process.ProcessName))  {   if(process.ProcessName.ToLower() == processName)   {   process.Kill();   }  }  } } /// <summary> /// 获取进程 /// </summary> /// <param name="pName"></param> /// <returns></returns> public static Process GetProcess(string pName) { if(string.IsNullOrWhiteSpace(pName)) return null; pName = pName.ToLower(); pName = pName.Replace(".exe", ""); //杀死主进程 Process[] processes = Process.GetProcesses(); foreach(Process process in processes) {  if(!string.IsNullOrWhiteSpace(process.ProcessName))  {  if(process.ProcessName.ToLower() == pName)  {   return process;  }  } } return null; }# endregion}

版本xml文件解析

public class UpgradeModel{ /// <summary> /// 初始化对象 /// </summary> /// <param name="xml"></param> public void LoadUpgrade(string xml) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xml); //读取UpgradeUrl XmlNode node = xmlDoc.SelectSingleNode("//UpgradeUrl"); if(node != null) {  this.UpgradeUrl = node.InnerText; } //读取RunMain node = xmlDoc.SelectSingleNode("//RunMain"); if(node != null) {  this.RunMain = node.InnerText; } //读取RunMain node = xmlDoc.SelectSingleNode("//AutoUpgrade"); if(node != null) {  this.AutoUpgrade = node.InnerText; } //读取Files node = xmlDoc.SelectSingleNode("Upgrade/Files"); this.DictFiles = new Dictionary < string, string > (); if(node != null && node.ChildNodes.Count > 0) {  foreach(XmlNode item in node.ChildNodes)  {  if(item.Name != "#comment")  {   string name = GetNodeAttrVal(item, "Name");   string version = GetNodeAttrVal(item, "Version");   if(!this.DictFiles.ContainsKey(name))   {   this.DictFiles.Add(name, version);   }  }  } } } private string GetNodeAttrVal(XmlNode node, string attr) {  if(node != null && node.Attributes != null && node.Attributes[attr] != null)  {  string val = node.Attributes[attr].Value;  if(!string.IsNullOrWhiteSpace(val))  {   return val.Trim();  }  return val;  }  return string.Empty; } /// <summary> /// 服务器地址 /// </summary> public string UpgradeUrl { get; set; } /// <summary> /// 更新完成后运行的主程序名称 /// </summary> public string RunMain { get; set; } /// <summary> /// 更新程序名称 /// </summary> public string AutoUpgrade { get; set; } /// <summary> /// 文件列表 /// string 文件名 /// string 版本号 /// </summary> public Dictionary < string, string > DictFiles { get; set; }}

服务端

服务端主Xml版本文件,包含所有的项目文件,客户端根据每个文件的版本号进行判断是否需要更新。如果需只更新某几个文件,则将对应文件的版本号更改只更高的版本号即可

版本xml文件

<?xml version="1.0" encoding="utf-8" ?><Upgrade> <!--服务器地址--> <UpgradeUrl>http://localhost:17580</UpgradeUrl> <!--更新完成后运行的主程序名称--> <RunMain>ClientMain.exe</RunMain> <!--更新程序名称--> <AutoUpgrade>AutoUpgrade.exe</AutoUpgrade> <Files> <!--更新文件列表,以Version为标志,当Version改变时,客户端启动会自动更新。子路径格式:\image\index.jpg--> <File Version="01" Name="\image\index.jpg" /> <File Version="01" Name="ClientMain.exe" /> <File Version="01" Name="AutoUpgrade.exe" /> </Files></Upgrade>

服务端主要提供连个可以通过Http的get或post访问的路径。一个用于获取版本Xml文件内容,一个用于下载指定文件的路径。以下代码示例通过asp.net mvc进行实现。大家可以根据自己技术方式参照实现。

自动升级服务Controller

/// <summary>/// 自动升级服务/// </summary>public class UpgradeController: Controller{ // // GET: /Upgrade/ /// <summary> /// 获取更新文件列表 /// </summary> /// <returns></returns> public object UpgradeList() {  string cacheKey = "Upgrade_UpgradeList.xml";  string resStr = CommonLibrary.CacheClass.GetCache < string > (cacheKey);  if(string.IsNullOrWhiteSpace(resStr))  {  string fileName = Server.MapPath(@"~\App_Data\UpgradeList.xml");  if(System.IO.File.Exists(fileName))  {   resStr = System.IO.File.ReadAllText(fileName);   CommonLibrary.CacheClass.SetCacheMins(cacheKey, resStr, 1);  }  }  return resStr; } /// <summary> /// 生成更新文件 /// </summary> /// <returns></returns> public object Create() {  UpgradeFileManager.CreateFiles(Server.MapPath("/App_Data"));  return "ok"; } /// <summary> /// 下载文件 /// </summary> /// <param name="fileName"></param> /// <returns></returns> public object DownloadFile() {  string fileName = PageRequest.GetString("fileName");  fileName = Server.MapPath(string.Format(@"~\App_Data\{0}", fileName));  return File(fileName, "application/octet-stream"); } /// <summary> /// 异常处理 /// </summary> /// <param name="filterContext"></param> protected override void OnException(ExceptionContext filterContext) { filterContext.HttpContext.Response.StatusCode = 400; filterContext.Result = Content(filterContext.Exception.GetBaseException().Message); filterContext.ExceptionHandled = true; }}

版本文件自动生成帮助类

/// <summary>/// 此类主要作用,对于项目文件非常多,自己手动编辑很麻烦,可以采用此方法,指定目录自动生成初始化的版本文件/// </summary>public class UpgradeFileManager{ /// <summary> /// 创建版本文件 /// </summary> /// <param name="path"></param> public static void CreateFiles(string path) {  List < string > dirList = new List < string > ();  GetAllDirt(path, dirList); //获取所有目录  dirList.Add(path);  System.Text.StringBuilder xml = new System.Text.StringBuilder();  xml.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");  xml.AppendLine(" <Files>");  foreach(var diry in dirList)  {  string[] files = Directory.GetFiles(diry);  foreach(string filePath in files)  {   FileInfo info = new FileInfo(filePath);   string name = filePath.Replace(path, "");   if(info.Directory.FullName == path)   {   name = name.Remove(0, 1);   }   xml.AppendLine(string.Format(" <File Version=\"1\" Name=\"{0}\" />", name));  }  }  xml.AppendLine("</Files>");  using(StreamWriter sw = new StreamWriter(Path.Combine(path, "UpgradeList_Temp.xml")))  {  sw.Write(xml);  sw.Close();  } } /// <summary> /// 获取所有子目录 /// </summary> /// <param name="curDir"></param> /// <param name="list"></param> private static void GetAllDirt(string curDir, List < string > list) { string[] dirs = Directory.GetDirectories(curDir); if(dirs.Length > 0) {  foreach(string item in dirs)  {  list.Add(item);  GetAllDirt(item, list);  } } }}

看完上述内容,你们掌握使用c#怎么自动更新程序的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程网行业资讯频道,感谢各位的阅读!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯