Do the development of people, especially to do the client (c/s) system development people will encounter a headache problem, is the automatic update of software, the system after the release of the Automatic Update program, under the fortunate to develop an automatic update program, update program and any host program is completely independent Just start the update in the main program, the update is also an executable file, at startup can be set whether it is automatic update and whether it is a manual update, automatic Update means that does not require manual intervention to download the update package from the remote server, And if the manual update will involve the user to click the button in the program to implement the update, in the Automatic Update and manual update can be based on the needs of the project to choose, some programs must require users to update to continue to use, so the program automatically update is necessary; Manual update is the user can update the program at any time, Do not need to strictly control the version of the problem, I would like to talk about the specific implementation details, I posted part of the code, the source of the company's property is not appropriate to upload;
The purpose of the automatic Update is to copy the DLL files on the server to the local execution directory and overwrite the local file with the same name; The process is simple, but there are several places to be aware of it:
1. How to download a large number of DLL files to the local, there are multiple DLL files in the download process if the speed of the situation may be lost packets, lost files and so on; My implementation is to package multiple files through the Icsharpcode.sharpziplib component, which can save a lot of things; For example, the name of the DLL for a dynamic connection library file may change in the case of the transfer process)
2. Download to the local, how to overwrite the original file with the same name, my implementation is the same name of the file support Delete, and then extract, this process needs to temporarily save the deleted files, prevent the operation failure program cannot start, pay attention to the principle of transactional;
3. If the updated file is not just a DLL file may also have some unlimited folder, my implementation is if there is a folder with the same name, the direct recursive delete, and then extract it into the directory; because the top-level directory after the decompression package is the name of the compressed file, All in the process of replication need to pay attention to the hierarchical relationship of the directory;
Let's take a look at the implementation of the entire process, although not the entire source code, but if you read this article basic implementation of no big problem;
For ease of deployment I recommend that you get a little trouble. Implement a deployment file tool, all files are packaged directly in the same time to generate server-side version information files;
The use of this tool is very convenient to implement the file compression, generate hash value, version files, update address and other information;
This XML is stored in the current version of the service, update the name of the file, update the hash value of the file, why the need to hash is afraid to update the file in some cases by the person switched, if all the client update after the consequences are serious; so we have to bring the hash value;
Tool to generate two files, one is the version of the file is an update package, the server's task has been completed, the following is the implementation of the specific client;
To know when a version update is required, keep a file in the client program directory that is used to record the version information;
The file holds the current local version number, the update address of the server, the name of the host program, need the name of the host to be able to update the host program in the process of enumeration and then shut down, so that it does not affect our update, of course, can also implement the host program is not closed in the case of updates, If the use of some already occupied by the host program will directly affect the update process, so in case of close to good;
This is the information stored in the client version file;
We said above, the update is divided into manual and automatic, we first to manually update it, manual update is the need for users to click the Update button and then start updating, the problem we can use the process of parameter delivery solution;
Of course, in the update process need to have this aspect of logic judgment;
The entrance of the place we make judgments, update the way; here the download remote update package is used WebClient object, you can also use other socket-based objects; Before the update begins, you need to determine whether the local version number is less than the remote version number, if it is less than the update;
Because the process of downloading is asynchronous, it is necessary to use the background thread to suggest that everyone uses the System.ComponentModel.BackgroundWorker background thread object, he has a good encapsulation of thread; Here's a look at the core process code:
| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 66676869 |
//开始辅助线程操作 privatevoidBack_thread_DoWork(object sender, DoWorkEventArgs e) { try { //实例化下载对象 downclient = newWebClient(); downclient.DownloadProgressChanged += newDownloadProgressChangedEventHandler(downclient_DownloadProgressChanged); downclient.DownloadFileCompleted += newAsyncCompletedEventHandler(downclient_DownloadFileCompleted); //下载远程更新包down.zip压缩文件|放在应用程序目录下|相应界面事件 downclient.DownloadFileAsync(newUri(Util.GetUpdateUrl() + "down.zip"), Util.GetDictiory() + "\\down.zip"); } catch(Exception err) { System.Diagnostics.Debug.WriteLine(err); } } //在异步下载结束时触发该事件 voiddownclient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { try { if(e.Error != null) { eventLog1.WriteEntry(e.Error.ToString()); MessageBox.Show("在进行远程更新时,发生错误", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { Util.KillProcess();//关闭主进程 //验证哈希值 if(Util.IsHash(Util.GetHash(Util.GetDictiory() + "\\down.zip"), FileWork.GetDownHash())) { //删除无用压缩文件 File.Delete(Util.GetDictiory() + "\\down.zip"); //删除无用版本文件 File.Delete(Util.GetDictiory() + "\\ServerUpdateFiles.xml"); MessageBox.Show("远程服务器更新包已发生变化,无法更新", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Error); eventLog1.WriteEntry("远程服务器中的更新包在制作和下载时间段中数据包发生变化,为了安全期间不给予下载!"); this.Close(); } else { //解压压缩包文件 ReduceToUnReduceFile.unZipFile(Util.GetDictiory() + "\\down.zip", Util.GetDictiory()); //删除压缩包文件 File.Delete(Util.GetDictiory() + "\\down.zip"); //检查文件夹层次结构 FileWork.LookFiles(Util.GetDictiory() + "\\down", Util.GetDictiory()); //订阅复制文件事件 FileWork.CopyFileEvent += newFileWork.CopyFileDelegate(FileWork_CopyFileEvent); //递归复制文件 FileWork.CopyFiles(Util.GetDictiory() + "\\down", Util.GetDictiory()); //删除临时文件夹 FileWork.DeleteFiles(Util.GetDictiory() + "\\down"); //如果库结构更新成功,则才能更新程序的版本号,否则下次继续更新 if(EventChainReference.GlobalEventChain.OnAutoUpdateDb()) //更新本地版本号信息 Util.UpdateLocalXml(); File.Delete(Util.GetDictiory() + "\\ServerUpdateFiles.xml"); MessageBox.Show("升级成功!", "信息提示"); Util.StartProcess(); isupdate = true; } } } catch(Exception err) { eventLog1.WriteEntry(err.ToString()); } Application.Exit(); } |
This part of the code is a concatenation of the entire process of code;
Automatic Update is probably finished, a few key places are given, I hope to develop automatic updating procedures for everyone to help;
C # implementation (Automatic Update)