[搜片神器]winform程序自己如何更新自己的方法代码
DHT抓取程序开源地址:https://github.com/h31h31/H31DHTDEMO
数据处理程序开源地址:https://github.com/h31h31/H31DHTMgr
国外测试服务器: http://www.sosobta.com 大家可以给提点意见...
--------------------------------------------------------------------------------------------------------------------
关于自动更新,在.NET下面已经是很普通的事情,无非就是在服务器端保存配置好要更新的程序,然后客户端再写一个小程序来检测,有更新的则复制过来。
但现在问题是就一个程序,如何让程序自己进行更新而不用调用另外的程序,对于用户来说体验更好.
如何让程序自己更新自己的方法1:
- 1.首先程序exe自己下载覆盖自己肯定是不行的,会报“当前程序正在被另一个进程所使用”的系统错误;
- 2.在进程中的程序不能覆盖自己,但是可以重命名,你从远程下载一个新的exe文件,重命名为xxx.exe.tmp;
- 3.待下载完毕后,把旧的exe重命名一下,比如xxx.exe.old,然后把新的xxx.exe.tmp重命名为xxx.exe;
- 4.重命名的方法:System.IO.File.Move(filepath + ".tmp", filepath);
- 5.然后重启程序Application.Restart();在form_Load事件里面判断一下
- if (System.IO.File.Exists(AppDomain.CurrentDomain.BaseDirectory + @"xxx.exe.old"))
- System.IO.File.Delete(AppDomain.CurrentDomain.BaseDirectory + @"xxx.exe.old");
- 这样就可以了,如果做的再好点的话,可以把xxx.exe.old的文件属性设置为隐藏就好了.
如何让程序自己更新自己的方法2:
网上搜索的方法:
如果建一个bat文件,执行的是复制功能,然后再用一个bat来调用他,并且用一个bat文件去杀掉某一个文件,然后再复制新的,再启动是没有什么问题的吧。
添加了一个方法KillSelfThenRun()用于删除正在运行的主Exe,然后再重启新的主Exe。代码全部粘贴如下:
private void KillSelfThenRun()
{
string strXCopyFiles = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "XCopyFiles.bat");
using (StreamWriter swXcopy = File.CreateText(strXCopyFiles))
{
string strOriginalPath = tempUpdatePath.Substring(0, tempUpdatePath.Length - 1);
swXcopy.WriteLine(string.Format(@"
@echo off
xcopy /y/s/e/v " + strOriginalPath + " " + Directory.GetCurrentDirectory() +"", AppDomain.CurrentDomain.FriendlyName));
}
string filename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "killmyself.bat");
using (StreamWriter bat = File.CreateText(filename))
{
// 自删除,自啟動
bat.WriteLine(string.Format(@"
@echo off
:selfkill
attrib -a -r -s -h ""{0}""
del ""{0}""
if exist ""{0}"" goto selfkill
call XCopyFiles.bat
del XCopyFiles.bat
del /f/q " + tempUpdatePath+Environment.NewLine + " rd " + tempUpdatePath +Environment.NewLine + " start " + mainAppExe +Environment.NewLine + " del %0 ", AppDomain.CurrentDomain.FriendlyName));
}
// 启动自删除批处理文件
ProcessStartInfo info = new ProcessStartInfo(filename);
info.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(info);
// 强制关闭当前进程
Environment.Exit(0);
}
第三步调用时,原程序本身就有一个Try的做法,就在Catch里面判断一下,如果出现IOException,就调用这个方法。
private void btnFinish_Click(object sender, System.EventArgs e)
{
this.Dispose();
//KillSelfThenRun();
try
{
CopyFile(tempUpdatePath, Directory.GetCurrentDirectory());
System.IO.Directory.Delete(tempUpdatePath, true);
}
catch (Exception ex)
{
if (ex.GetType() == typeof(IOException))
{
KillSelfThenRun();
}
else
{
MessageBox.Show(ex.Message.ToString());
}
}
if (true == this.isRun) Process.Start(mainAppExe);
}
经过分析后还是觉得第一种方法来得快些,简单易用:
先看使用方法:
在主程序界面里面增加一个定时器,然后用来延时来判断服务器上的程序是否有更新,如果在程序一开始就判断,程序会加载很慢,从而给用户体验不好.
- string m_localPath = AppDomain.CurrentDomain.BaseDirectory;
- string thisexename = Application.ExecutablePath.Replace(m_localPath, "");
- H31Updater update1 = new H31Updater();
- bool isupdate = update1.CheckServerUpdate(m_localPath, thisexename);
- if (isupdate)
- {
- DialogResult dlg = MessageBox.Show(this, "检测到服务器上有新版本,需要更新么?", "信息提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
- if (dlg == DialogResult.OK)
- {
- update1.Show();
- update1.UpdaterStart();
- }
- }
然后程序就会显示更新进度条:
程序更新后将自己命令为*.old,然后使用MOVE命令将新的更新为自己.
服务器上的返回XML文件列表方式:
- <?xml version="1.0" encoding="utf-8" ?>
- <AutoUpdater>
- <UpdateInfo id="">
- <Version value = "1.0.0.3"/>
- </UpdateInfo>
- <!--升级文件列表-->
- <UpdateFileList>
- <UpdateFile>software\H31Thunder.exe</UpdateFile>
- <!--可以复制多行,更新自己目录下面的程序-->
- <UpdateFile>software\H31Thunder.exe</UpdateFile>
- </UpdateFileList> </AutoUpdater>
上面配置的XML文件列表可以复制多行来执行多个更新.
现将自己经过测试的代码提供给大家讨论学习下,希望大家能够用到:
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Text;
- using System.Windows.Forms;
- using System.Globalization;
- using System.IO;
- using System.Net;
- using System.Xml;
- using System.Threading;
- namespace H31Thunder
- {
- public partial class H31Updater : Form
- {
- private WebClient downWebClient = new WebClient();
- private static string m_exePath = "";
- private static string m_exeName = "";
- private static string m_url = "http://h31bt.com/";
- private static string[] fileNames;
- private static int m_downNowPos;//已更新文件数
- private static string fileName;//当前文件名
- public H31Updater()
- {
- InitializeComponent();
- }
- public bool CheckServerUpdate(string exePath,string exeName)
- {
- m_exePath = exePath;
- m_exeName = exeName;
- if (File.Exists(m_exePath + m_exeName + ".old"))
- File.Delete(m_exePath + m_exeName + ".old");
- string currentVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
- string theNewVersion = GetTheNewVersion(m_url + "version.asp?id=1");
- if (!String.IsNullOrEmpty(theNewVersion) && !String.IsNullOrEmpty(currentVersion))
- {
- if (string.Compare(theNewVersion,currentVersion)> )
- {
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// 开始更新
- /// </summary>
- public void UpdaterStart()
- {
- try
- {
- float tempf;
- //委托下载数据时事件
- this.downWebClient.DownloadProgressChanged += delegate(object wcsender, DownloadProgressChangedEventArgs ex)
- {
- this.label2.Text = String.Format(CultureInfo.InvariantCulture,"正在下载:{0} [ {1}/{2} ]",fileName,ConvertSize(ex.BytesReceived),ConvertSize(ex.TotalBytesToReceive));
- tempf = ((float)(m_downNowPos) / fileNames.Length);
- this.progressBar2.Value = ex.ProgressPercentage;
- this.progressBar1.Value = Convert.ToInt32(tempf * );
- };
- //委托下载完成时事件
- this.downWebClient.DownloadFileCompleted += delegate(object wcsender, AsyncCompletedEventArgs ex)
- {
- if (ex.Error != null)
- {
- MeBox(ex.Error.Message);
- }
- else
- {
- if (fileNames.Length > m_downNowPos)
- {
- DownloadFile(m_downNowPos);
- }
- else
- {
- this.progressBar1.Value = this.progressBar1.Maximum;
- this.progressBar2.Value = this.progressBar2.Maximum;
- Thread.Sleep();
- UpdaterClose();
- }
- }
- };
- m_downNowPos = ;
- if (fileNames != null)
- DownloadFile();
- }
- catch (WebException ex)
- {
- MeBox(ex.Message);
- }
- }
- /// <summary>
- /// 下载文件
- /// </summary>
- /// <param name="arry">下载序号</param>
- private void DownloadFile(int arry)
- {
- try
- {
- m_downNowPos++;
- int findpos = fileNames[arry].LastIndexOf("/");
- if (findpos != -)
- fileName = fileNames[arry].Substring(findpos+, fileNames[arry].Length - findpos-);
- else
- fileName = fileNames[arry];
- this.label1.Text = String.Format(CultureInfo.InvariantCulture, "更新进度 {0}/{1}", m_downNowPos, fileNames.Length);
- this.progressBar2.Value = ;
- string weburl = m_url + fileNames[arry];
- string savename=m_exePath + fileName + ".new";
- this.downWebClient.DownloadFileAsync(new Uri(weburl), savename);
- }
- catch (Exception ex)
- {
- MeBox(ex.Message);
- }
- }
- /// <summary>
- /// 关闭程序
- /// </summary>
- private static void UpdaterClose()
- {
- try
- {
- if (File.Exists(m_exePath + m_exeName + ".old"))
- File.Delete(m_exePath + m_exeName + ".old");
- for(int i=;i<fileNames.Length;i++)
- {
- int findpos = fileNames[i].LastIndexOf("/");
- string savename = fileNames[i];
- if(findpos!=-)
- savename = fileNames[i].Substring(findpos+, fileNames[i].Length - findpos-);
- if (File.Exists(m_exePath + savename + ".old"))
- File.Delete(m_exePath + savename + ".old");
- File.Move(m_exePath + savename, m_exePath + savename + ".old");
- File.Move(m_exePath + savename + ".new", m_exePath + savename);
- File.SetAttributes(m_exePath + savename + ".old", FileAttributes.Archive | FileAttributes.Hidden);
- }
- }
- catch (Exception ex)
- {
- //if (ex.GetType() == typeof(IOException))
- //{
- //}
- //else
- MeBox(ex.Message);
- }
- Application.Exit();
- }
- /// <summary>
- /// 判断软件的更新日期
- /// </summary>
- /// <param name="Dir">服务器地址</param>
- /// <returns>返回日期</returns>
- private static string GetTheNewVersion(string webUrl)
- {
- string NewVersion = "";
- try
- {
- WebClient wc = new WebClient();
- Stream getStream = wc.OpenRead(webUrl);
- StreamReader streamReader = new StreamReader(getStream, Encoding.UTF8);
- string xmltext = streamReader.ReadToEnd();
- streamReader.Close();
- XmlDocument xmlDoc = new XmlDocument();
- xmlDoc.InnerXml = xmltext;
- XmlNode root = xmlDoc.SelectSingleNode("//Version");
- if (root.Name == "Version")
- {
- NewVersion = root.Attributes["value"].Value.ToString();
- }
- XmlNodeList root1 = xmlDoc.SelectNodes("//UpdateFileList");
- if (root1 != null)
- {
- fileNames = new string[root1.Count];
- int i=;
- foreach (XmlNode temp in root1)
- {
- fileNames[i] = temp.InnerText.Replace("\\","/");
- i++;
- }
- }
- }
- catch (WebException ex)
- {
- //MeBox(ex.Message);
- }
- return NewVersion;
- }
- /// <summary>
- /// 弹出提示框
- /// </summary>
- /// <param name="txt">输入提示信息</param>
- private static void MeBox(string txt)
- {
- MessageBox.Show(txt, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
- }
- /// <summary>
- /// 转换字节大小
- /// </summary>
- /// <param name="byteSize">输入字节数</param>
- /// <returns>返回值</returns>
- private static string ConvertSize(long byteSize)
- {
- string str = "";
- float tempf = (float)byteSize;
- if (tempf / > )
- {
- if ((tempf / ) / > )
- {
- str = ((tempf / ) / ).ToString("##0.00", CultureInfo.InvariantCulture) + "MB";
- }
- else
- {
- str = (tempf / ).ToString("##0.00", CultureInfo.InvariantCulture) + "KB";
- }
- }
- else
- {
- str = tempf.ToString(CultureInfo.InvariantCulture) + "B";
- }
- return str;
- }
- }
- }
程序自动更新类代码
如果大家有什么更好的方法,请指教.谢谢.
下载程序:H31Thunder.rar
下一篇给大家介绍上面图中显示如何从迅雷服务器上偷用视频图片地址的方法.不信的话大家可以去查看下图片的 http://www.sosobta.com 网址是不是自己服务器上的...
当然希望大家多多推荐哦...大家的推荐才是下一篇介绍的动力...
[搜片神器]winform程序自己如何更新自己的方法代码的更多相关文章
- MFC编辑框接收数据动态更新与刷新方法代码示例-如何让编辑框内容实时更新
MFC编辑框接收数据动态更新与刷新方法代码示例-如何让编辑框内容实时更新 关键代码: //发送数据通知 //from txwtech@163.com LRESULT CCommSampleDlg::O ...
- 分析nuget源码,用nuget + nuget.server实现winform程序的自动更新
源起 (个人理解)包管理最开始应该是从java平台下的maven开始吧,因为java的开发大多数是基于开源组件开发的,一个开源包在使用时很可能要去依赖其他的开源包,而且必须是特定的版本才可以.以往在找 ...
- [搜片神器]之DHT网络爬虫的C++程序初步开源
回应大家的要求,特地整理了一开始自己整合的代码,这样最简单,最直接的可以分析流程,至于文章里面提供的程序界面更多,需要大家自己开发. 谢谢园子朋友的支持,已经找到个VPS进行测试,国外的服务器: ht ...
- [C#搜片神器] 之P2P中DHT网络爬虫原理
继续接着上一篇写:使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)[搜片神器] 昨天由于开源的时候没有注意运行环境,直接没有考虑下载BT种子文件时生成子文件夹,可能导致有的朋友运行 ...
- [搜片神器]之DHT网络爬虫的代码实现方法
继续接着第一篇写:使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)[搜片神器] 谢谢园子朋友的支持,已经找到个VPS进行测试,国外的服务器: http://www.sosobta. ...
- C# winform程序怎么打包成安装项目(VS2010图解)
作为研发人员,在本机上开发的winform.wpf或者控制台程序需要发给其他人测试时候,一般需要对其进行打包生成setup安装文件,根据网上查找的资料并结合自己打包成功,记录如下: 注:本程序是一个利 ...
- 用winform程序来了解委托和事件
一.浅谈委托 如果有个过winform 和webform 程序开发的小伙伴一定有个这样的感觉吧,点击Button直接就执行了那个方法,到此他是怎么实现了的呢,大家有考虑过没有? 回到正题,什么是委托呢 ...
- 黄聪:C#Winform程序如何发布并自动升级(图解)
有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解)其实打包是打包,发 ...
- 【转】C#Winform程序如何发布并自动升级(图解)
有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解)其实打包是打包,发 ...
随机推荐
- Part 8 AngularJS filters
Filters in angular can do 3 different things 1. Format data 2. Sort data 3. Filter data Filters can ...
- 番外篇 之 C#委托
对于上一节 番外篇之C#多线程的反思 反思一: Thread th = new Thread(参数); ////参数的总结 ////首先,第一情况,对于 Thread th = new Threa ...
- C#读写日志文本文件
日志为文本文件每列以制表符隔开 行以换行符隔开 本次示例简单实现如下相关功能:1.正写日志文本 最新的日志放后面2.倒写日志文本 最新的日志放前面3.读日志文本内容显示在Label4.读日志文本内容到 ...
- iOS学习笔记--OC系列(1)
前言 从学校毕业进入公司工作已经第3个年头了,回顾这3年的经历,有种迷茫的感觉.在公司我主要是做零售业公司的系统维护,接触的主要是Oracle的Database的东西.但是业务知识和oracle,都没 ...
- Codevs 1083 Cantor表
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题目描述 Description 现代数学的著名证明之一是Georg Cantor证明了有理数是可枚举的 ...
- floodfill算法解题示例
Flood fill算法是从一个区域中提取若干个连通的点与其他相邻区域区分开(或分别染成不同颜色)的经典算法.因为其思路类似洪水从一个区域扩散到所有能到达的区域而得名.在GNU Go和扫雷中,Floo ...
- RHEL(RedHat Enterprise Linux)5/6 ISO镜像下载
本文贴出了RHEL(RedHat Enterprise Linux)发行版本中常用的服务器版本的ISO镜像文件,供大家下载学习使用,贴出的版本有RedHat Enterprise Linux(RHEL ...
- 学习CentOS7笔记(一)
说明: 1.这是我第一次接触CentOS7,从基础学起. 2.最终目的是为了在CentOS上面部ngix+php+mysql+naxsi环境,进行安全测试. 第一部分 认识CentOS 7 有时候我在 ...
- 图片剪裁上传插件 - cropper
图片剪裁上传插件 - cropper <style> .photo-container{float: left;width: 300px;height: 300px;} .photo-co ...
- .Net Core下如何管理配置文件(转载)
原文地址:http://www.cnblogs.com/yaozhenfa/p/5408009.html 一.前言 根据该issues来看,System.Configuration在.net core ...