Automatic update of programs in C #. Part 2

    A few days ago I wrote an article on the implementation of automatic software updates in C #.

    Taking into account the constructive criticism of the commentators, it was decided to improve that code by adding several new features, including improving the "old" ones:
    • Automatic check, download and install updates;
    • Providing the user with the opportunity to choose the moment of update (new) ;
    • Improved file version verification mechanism;
    • Checking the integrity of the update file (new)

    In order not to retype the text of the previous article , in this I focus only on the processed parts of the code.


    Key points


    Commentators of the previous article identified the following code flaws (I indicate only those that I relied on):
    • It’s only better to download a new file first, so that the situation does not happen when in the middle of the download, for some reason, the application terminates and the user remains with the .bak files and incomplete .exe, i.e. without a working application. ( DarkByte );
    • Just did not see the checksum check. ( naum );
    • To show the user a modal (most likely) information window with a single “Ok” button without leaving a choice is not a good practice. You need to do everything quietly and imperceptibly, or unobtrusively offer to upgrade with the ability to do it somehow later, when the user is more convenient. ( iroln );
    • The version comparison you have is incorrect. Problems will be, for example, when upgrading from 9.12.2 to 10.0.0. ( eyeless_watcher )
    • And what prevents directly comparing Version types? ( teleavtomatika ).

    There were, of course, other comments similar to these, but I did not give them all, and I propose to proceed to consider the problems.

    Amendment


    Since some error may occur while downloading the file, as a result of which the file will be damaged, the following amendments were made to the code:

    public void checkUpdates(){
    	try
    	{
    		if (File.Exists("launcher.update") && new Version(FileVersionInfo.GetVersionInfo("launcher.update").FileVersion) > new Version(Application.ProductVersion))
    		{
    			Process.Start("updater.exe", "launcher.update \"" + Process.GetCurrentProcess().ProcessName + "\"");
    			Process.GetCurrentProcess().CloseMainWindow();
    		}
    		else
    		{
    			if (File.Exists("launcher.update")) { File.Delete("launcher.update"); }
    			Download();
    		}
    	}
    	catch (Exception)
    	{
    		if (File.Exists("launcher.update")) { File.Delete("launcher.update"); }
    		Download();
    	}
    }
    

    First, we check if the launcher.update update file exists , and also check the version of the file, since its extension is not important for us. If the file is damaged, the try catch exception handler will work by executing the code to delete the damaged file and then launch the function of checking and downloading (if found) updates on the site.
    If the file turns out to be the whole and its version will be higher than the current one, the additional updater.exe utility is launched to carry out operations to replace the main program file. I won’t write more details, as it was already earlier .

    Thus, we will verify the integrity of the update file.

    private void Download()
    {
    	try
    	{
    		XmlDocument doc = new XmlDocument();
    		doc.Load(@"http://mysite/version.xml");
    		remoteVersion = new Version(doc.GetElementsByTagName("version")[0].InnerText);
    		localVersion = new Version(Application.ProductVersion);
    		if (localVersion < remoteVersion)
    		{
    			if (File.Exists("launcher.update")) { File.Delete("launcher.update"); }
    			WebClient client = new WebClient();
    			client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
    			client.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
    			client.DownloadFileAsync(new Uri(@"http://mysite/launcher.exe"), "launcher.update");
    		}
    	}
    	catch (Exception) { }
    }
    

    Further, the function of the file version verification process has undergone changes, the key point of which is the implementation of file version comparison using the built-in System.Version tools , as a result of which the problem of correct version verification, say, “9.12.2” and “10.0.0”, has been eliminated.
    In the event that a newer version is detected, the actions are as follows: the program automatically downloads the update file in the background, then gives the user a message about the availability of this update and offers a choice of 2 options for the development of events:
    1. By agreeing to an update , the program instantly restarts, having performed all the necessary actions;
    2. Refusing to update the program stores the file next to the executable file, where it was downloaded. In this option, the update process will occur the next time the program starts without displaying any notifications.


    Conclusion


    The rewritten code turned out to be more perfect in comparison with the previous version, and also eliminates the likelihood of applying the update to the “bit” file, as well as the lack of the implementation of the function of checking the checksum of the downloaded file with the version on the server.

    And I would like to say special thanks to the following people for their constructive criticism: DarkByte , naum , iroln , eyeless_watcher , teleavtomatika , wire .

    Regards, Andrew Helldar!

    PS: kind people from among the minusers - please be kind in the comments write why you decided so. It is interesting to know where I am wrong.

    UPD. We kindly ask those who still have thoughts about “crooked hands”, “crooked code”, etc., write in the comments at least what's wrong. Based on your constructive criticism, I will improve my work, thereby learning how to write better code.
    Thanks in advance!

    Also popular now: