C#编写软件升级更新程序的完整示例(c反应蛋白高说明什么)

一个软件在做调整以后,都是要升级更新的,如果这个时候要求用户重新去下载,体验非常不好,所以程序一运行起来,就应该判断是不是要更新,如果要的话,直接自动更新,再运行,这样用户体验会好很多。


任务过程:更新的文件是放在一个远程目录http://192.168.1.100/Resourse/Update/中,软件启动后,先判断是不是需要更新,如果要,去远程目录下载文件更新,然后再运行,中间需要用户看到下载更新的过程

效果如图:这里我只是实现的过程,细节比如文字啥的比较简单,就没有弄

C#编写软件升级更新程序的完整示例(c反应蛋白高说明什么)


1、创建一个名为Update的项目,窗体名称改为DownFileFromURL,窗体代码如下:(大多数函数我已经弄好,直接复制就可以,注释的地方看下应该不难)

using System;using System.Diagnostics;using System.IO;using System.Net;using System.Threading;using System.Windows.Forms;namespace Update{ public partial class DownFileFromURL : Form { string webURL; //远程下载文件地址 string[] FileNames; //要下载的文件名数组 //下载的文件是否加上tmp,这个是我当时做别的加的功能,这里没什么用 string ReName; //更新成功后,运行哪个文件 string RunEXEname; //完成成功标志,初始值为false bool ok = false; //构造函数 public DownFileFromURL(string theurl, string filenames, string renametoaddtmp,string runwho) { #region 调用示例 //string filenames = "a.exe|b.txt|c.bmp"; //string args = ""; ////下载地址 //string args = "http://192.168.1.100/Resourse/Update/ "; ////下载文件名字符串,用“|”隔开 //args = filenames " "; ////更新文件不改名 //args = "false" " "; ////更新结束后运行哪个文件 //args = "a.exe" " "; #endregion //初始化本地参数 webURL = theurl; FileNames = filenames.Split('|'); ReName = renametoaddtmp; RunEXEname = runwho; InitializeComponent(); } private void DownFileFromURL_Load(object sender, EventArgs e) { //在线程中操作控件值的话要加上下面这句话 CheckForIllegalCrossThreadCalls = false; label1.Text = "开始下载新版本,请稍等..."; Thread t = new Thread(new ThreadStart(DownFileGo)); t.Start(); } void DownFileGo() { int howmanyfiles = FileNames.Length; for (int i = 0; i < howmanyfiles; i ) { //逐个下载 DownFile(mybar, Application.StartupPath "", webURL "/" FileNames[i], ReName); if (i == howmanyfiles - 1) { //下载完以后如果参数中要求直接运行指定程序,就运行它 if (RunEXEname.Length != 0) { Process.Start(Application.StartupPath RunEXEname); } //成功标志改为true ok = true; this.Close(); break; } } } private void DownFile(ProgressBar thebar, string dir, string URL, string rename) { string filename = URL.Substring(URL.LastIndexOf("/") 1); string FileName = dir filename; //下载到其它目录下,dir参数未测试 if (rename == "true") { FileName = FileName ".tmp"; } //得到远程文件信息 HttpWebRequest Myrq = (HttpWebRequest)HttpWebRequest.Create(URL); HttpWebResponse myrp = (HttpWebResponse)Myrq.GetResponse(); long totalbytes = myrp.ContentLength; thebar.Maximum = (int)totalBytes; //常规文件流处理代码 Stream st = myrp.GetResponseStream(); Stream so = new FileStream(FileName.Replace(" ", " ").Replace("%20", " "), FileMode.Create); long totalDownloadedByte = 0; byte[] by = new byte[1024]; int osize = st.Read(by, 0, (int)by.Length); while (osize > 0) { totalDownloadedByte = osize totalDownloadedByte; Application.DoEvents(); so.Write(by, 0, osize); thebar.Value = (int)totalDownloadedByte; osize = st.Read(by, 0, (int)by.Length); if (thebar.Value == (int)totalBytes) { thebar.Value = 0; } } so.Close(); st.Close(); } private void DownFileFromURL_FormClosing(object sender, FormClosingEventArgs e) { //如果还没下载完,退出 if (!ok) { e.Cancel = true; } } }}

2、设置它的启动参数,修改program.cs

using System;using System.Collections.Generic;using System.Diagnostics;using System.Linq;using System.Reflection;using System.Threading.Tasks;using System.Windows.Forms;namespace Update{ static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main(string[] args) { Process instance = RunningInstance(); //这个程序是否运行,因为我自己用,所以我一直用进程名判断 if (instance == null) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); //如果参数个数正确 if (args.Length == 5) { string theurl = args[0]; string filenames = args[1]; string rename = args[2]; string runexename = args[3]; //这里先把自己的主程序进程杀掉, //再运行更新窗体 string killexename = args[4]; Kill(killexename); Application.Run(new DownFileFromURL(theurl, filenames, rename, runexename)); } else { MessageBox.Show("^#$#!#@!*^*@%#$#!@%rnrn@%#!@%!#@!*^@%#!@%!@%@%#$#!@%#@!*^rnrn#@!*^@%#!@%!@%#@!*^#$#@%!@%#@!*^#rnrn................"); } } else { Process.GetCurrentProcess().Kill(); } } /// <summary> /// 杀死进程 /// <para>Kill("winword");不带exe</para> /// </summary> /// <param name="pname">进程名称,不带exe</param> public static void Kill(string pname) { try { Process[] p = Process.GetProcesses(); foreach (Process tp in p) { if (tp.ProcessName == pname | tp.ProcessName.ToLower() == pname) { tp.Kill(); } } } catch { } } public static Process RunningInstance() { Process current = Process.GetCurrentProcess(); Process[] processes = Process.GetProcessesByName(current.ProcessName); foreach (Process process in processes) { if (process.Id != current.Id) { if (Assembly.GetExecutingAssembly().Location.Replace("/", "") == current.MainModule.FileName) { return process; } } } return null; } }}

经过这两步,更新程序本身就完成了,文件名就是项目名:update.exe.现在我们来看下如何用其它程序来调用它。

新建一个主程序 ksh.exe,在它运行时,比如可以放在program.cs中,加入以下模块

//我更改了数据库中的更新版本号//此时从库中读出来,也就是库中片版本号,当然也可以想其它办法string cmdstr = "select Cver from Ver";string dbver = GetFirstData(cmdstr);//当前片版本号//[assembly: AssemblyFileVersion("1.0")]//这个也可以把当前版本号放在xml中与dbver对比,更新完再更新xm即可string nowver = Application.ProductVersion;//更新文件文件名string exename = Application.StartupPath "Update.exe";//如果版本号不一致if (dbverf > nowverf) { //添加update.exe运行需要的参数 //下载地址 string args = "http://192.168.1.100/Resourse/Update/C "; //要下载的文件名列表 string filenames = "a.exe|b.txt|c.xml"; string[] filenamesarr = filenames.Split('|'); args = filenames " "; //下载的文件是否改名 args = "false" " "; //更新后运行哪个文件 args = "a.exe" " "; //我当前的进程名,因为要更新自己的话 //万一自己还没有退出,则需要让update.exe杀死自己 //当然你也可以让update检测,等它退出再更新 args = "ksh"; //运行update.exe RunINCMD(exename, args); //退出自己,准备更新 Application.ExitThread(); this.DialogResult = DialogResult.No;}void RunINCMD(string EXEname, string Args){ System.Diagnostics.Process Process1 = new System.Diagnostics.Process(); Process1.StartInfo.FileName = EXEname; Process1.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; Process1.StartInfo.Arguments = " " Args; Process1.Start(); Process1.WaitForExit();}

这样当ksh.exe运行后,就会先判断自己的版本号与远程版本号是不是一致,如果不一致,就提供update.exe需要的参数,然后运行update.exe,自己退出或被update.exe文件kill掉,保证更新进行。

在更新过程中,因为我是写在线程中的,所以有几个文件,大小多少,下载进度这些都是可控的,我没有写

最后,

//要下载的文件名列表

string filenames = "a.exe|b.txt|c.xml";

有一天你想在下载列表中新加一些文件,如果你这样写就得重新改程序,我用的方法是浏览更新文件目录,把目录下所有文件名读出来,这样你下次要求软件更新时,新增文件直接复制到远程目录中就可以了。

这个功能前几天我写过,有要用的可以点下面去看:

C#得到远程目录中的文件名称

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

(0)
上一篇 2023年3月24日 上午9:12
下一篇 2023年3月24日 上午9:17

相关推荐