Online Winform update and automatic winform update
Introduction
The first article in, Winform online update, is a heavy old business. When we first arrived in Beijing in, we had been working on hardware linkage programming. So we were engaged in Winform most of the time, however, I have never updated this function online. I joined another department project a few days ago and added an online update when I came up. The core of this automatic update component was developed by the temple knight. In addition, I did not know how to use it when I got the source code of this component. It took me half a day to debug the component, therefore, record the problems and solutions I encountered, so that you can view the usage methods when using other Coder.
Online update ideas
1. You can request a remote site Version. xml or a Web server. The major difference is to compare the server configuration file Version with the local configuration file Version.
2. download files from a remote site.
3. overwrite the Local Executable File and the Dll used, and disable the local exe process or windows service process before overwriting.
4. Modify the local configuration file AutoUpdater. config.
5. Restart the executable program or windows service after overwriting.
Disadvantages of AutoUpdater)
1. I didn't see how the anchor uses this component. I found the place where the main program was closed when referring to the anti-water cold dragon Demo.
2. When downloading a file, the local AutoUpdater. config is not processed when the Remote Server adds a file. That is to say, the update program is processed based on the local configuration file config. UpdateFileList.
3. There is no processing process for windows Services (windows Service Processing class has been improved ).
Problems encountered during use
1. Do not know how to use this component?
When using this component, the project should have four parts: the Web site is used to accept requests and download the files to be updated, the AutoUpdater update component, and the MainApplication (that is, your main program), UpdateApplication (update program entry, started through the main program, within which the AutoUpdater component is called ).
2. I don't know how to close the main program and windows Services.
In the Demo, we can see that the process is closed when you click "OK" before the file is downloaded.
If (bDownload) {// Disable windows service ServiceProcess serviceProcess = new ServiceProcess (); serviceProcess. stopService (); // turn off the main program OperProcess finished = new OperProcess (); stopped. initUpdateEnvironment (); DownloadConfirm dc = new DownloadConfirm (downloadList); if (this. onShow! = Null) this. OnShow (); if (DialogResult. OK = dc. ShowDialog () {StartDownload (downloadList );}}
3. The temporary directory after the file is downloaded is inconsistent with the main directory of the source program.
Adjust the file Copy and Move code as needed. The executable files and main Dll of our program are put in a separate file instead of the default Bin \ Debug file. So my approach is to move the downloaded file from TempFolder to the root directory of the executable source file. The specific code is processed in the ProcDownload method of the DownloadProgress form.
if (!string.IsNullOrEmpty(tempFolderPath)) { oldPath = Path.Combine(CommonUnitity.SystemBinUrl, file.FileName); newPath = Path.Combine(CommonUnitity.SystemBinUrl + ConstFile.TEMPFOLDERNAME + tempUrlPath, file.FileName); }
4. Suitable for starting the application after file download and mobile copy
Add finally code to the update program, start the windows Service, start the main program, and close the UpdateApplication ).
void InitAndCheck() { bool bHasError = false; IAutoUpdater autoUpdater = new AutoUpdater(); try { autoUpdater.Update(); } catch (WebException exp) { MessageBox.Show("Can not find the specified resource"); bHasError = true; } catch (XmlException exp) { bHasError = true; MessageBox.Show("Download the upgrade file error"); } catch (NotSupportedException exp) { bHasError = true; MessageBox.Show("Upgrade address configuration error"); } catch (ArgumentException exp) { bHasError = true; MessageBox.Show("Download the upgrade file error"); } catch (Exception exp) { bHasError = true; MessageBox.Show("An error occurred during the upgrade process"); } finally { if (bHasError == true) { try { autoUpdater.RollBack(); } catch (Exception) { } } ServiceProcess serviceProcess = new ServiceProcess(); serviceProcess.StartService(); OperProcess oper = new OperProcess(); oper.StartProcess(); } }
5. When a new file is added to the Web site, it is not synchronized to the local configuration file.
The source code shows that the local AutoUpdater. config is modified based on the Local UpdateFileList. You only need to add the new file information on the Web end to the List, and the local config will be synchronized during serialization.
LocalFile tempFile = null; foreach (RemoteFile file in listRemotFile. values) {downloadList. add (new DownloadFileInfo (file. url, file. path, file. lastVer, file. size); // Add the new Remote Server File to config. updateFileList: Modify the local AutoUpdater. config. TempFile = new LocalFile (file. Path, file. LastVer, file. Size); config. UpdateFileList. Add (tempFile); if (file. NeedRestart) bNeedRestart = true ;}
6. Add a windows Service Processing class
Public class ServiceProcess {# region determine whether the window service is started /// <summary> /// determine whether a Windows service is started /// </summary> /// <returns> </returns> private bool IsServiceStart (string serviceName) {ServiceController psc = new ServiceController (serviceName); bool bStartStatus = false; try {if (! Psc. status. equals (ServiceControllerStatus. stopped) {bStartStatus = true;} return bStartStatus;} catch (Exception ex) {throw new Exception (ex. message) ;}# endregion # region start service private bool StartService (string serviceName) {bool flag = true; if (ServiceIsExisted (serviceName) {System. serviceProcess. serviceController service = new System. serviceProcess. serviceController (serviceName); if (se Rvice. Status! = System. ServiceProcess. ServiceControllerStatus. Running & service. Status! = System. serviceProcess. serviceControllerStatus. startPending) {service. start (); for (int I = 0; I <60; I ++) {service. refresh (); System. threading. thread. sleep (1000); if (service. status = System. serviceProcess. serviceControllerStatus. running) {break;} if (I = 59) {flag = false ;}}} return flag ;}# endregion # region stop service private bool StopService (string serviceName) {bool flag = true; if (ServiceIsExisted (serviceName) {System. serviceProcess. serviceController service = new System. serviceProcess. serviceController (serviceName); if (service. status = System. serviceProcess. serviceControllerStatus. running) {service. stop (); for (int I = 0; I <60; I ++) {service. refresh (); System. threading. thread. sleep (1000); if (service. status = System. serviceProcess. serviceControllerStatus. stopped) {Break;} if (I = 59) {flag = false ;}}} return flag ;}# endregion # region checks whether the window service has private bool ServiceIsExisted (string serviceName) {ServiceController [] services = ServiceController. getServices (); foreach (ServiceController s in services) {if (s. serviceName = serviceName) {return true;} return false;} # endregion # region installation service private void InstallService (IDictionary stateSaver, String filepath) {try {ServiceController service = new ServiceController ("ServiceName"); if (! ServiceIsExisted ("ServiceName") {// Install Service AssemblyInstaller myAssemblyInstaller = new AssemblyInstaller (); myAssemblyInstaller. useNewContext = true; myAssemblyInstaller. path = filepath; myAssemblyInstaller. install (stateSaver); myAssemblyInstaller. commit (stateSaver); myAssemblyInstaller. dispose (); // -- Start Service service. start ();} else {if (service. status! = System. ServiceProcess. ServiceControllerStatus. Running & service. Status! = System. serviceProcess. serviceControllerStatus. startPending) {service. start () ;}} catch (Exception ex) {}# endregion # region uninstall windows Service private void UnInstallService (string filepath) {try {if (ServiceIsExisted ("ServiceName") {// UnInstall Service AssemblyInstaller myAssemblyInstaller = new AssemblyInstaller (); myAssemblyInstaller. useNewContext = true; myAssemblyInstaller. path = filepath; MyAssemblyInstaller. uninstall (null); myAssemblyInstaller. dispose () ;}} catch (Exception ex) {}# endregion public void StopService () {if (ServiceIsExisted ("MyService ")) {if (IsServiceStart ("MyService") {this. stopService ("MyService") ;}} public void StartService () {if (ServiceIsExisted ("MyService") {if (! IsServiceStart ("MyService") {this. StartService ("MyService ");}}}}
Summary
When any function needs to be developed, you must understand its principles and debug the source code found on the internet repeatedly. After debugging, you can understand the principles to better apply the function. When I first got this function, I didn't understand how to integrate it. It took me some time to figure out how to use it. I would like to thank you again for the inspiration provided by the Articles of the anchor and the document against the cold water.
Demo download and extract code 99a9