38

I am building a C# Windows application. I want it so whenever I click the update button in my form, the application will look for a new version available on my server.

If there is then proceed to update the software.

How is this usually handled?

jordanz
  • 367
  • 4
  • 12

6 Answers6

22

Take a look at Click Once. This thread might also make an interesting read.

Kurt Schelfthout
  • 8,880
  • 1
  • 30
  • 48
  • 1
    ClickOnce has one major drawback - it pops up its own window before starting your own application, which is ugly and confusing to first-time users. It should work like Firefox does, or Reflector... – Krzysztof Kozmic Apr 23 '09 at 09:03
  • I read that you can change that behaviour, for example here: http://bloggingabout.net/blogs/dennis/archive/2007/11/05/manual-check-for-updates-with-clickonce.aspx . – Lennaert Apr 23 '09 at 09:48
  • 3
    @Krzysztof, It doesn't need to do that. It all depends on how you configure and build your update solution. You can write all the clickonce interaction inside your application without the need for the framework-provided dialogs. – J. Steen Apr 23 '09 at 09:49
  • The first link is dead – piegames Apr 30 '22 at 13:54
13

Let me start by saying we offer a complete updating solution which includes:

wyUpdate handles all of the Vista/Windows 7 UAC problems and all the file permission problems that inevitably pop up when you're trying to update complex software.

That being said, if you want to build your own updater here are some tips:

Building your own updater

A good place to start is the wyUpdate C# source code I mentioned above. You can cannibalize it and use it for your own purposes. Some of the algorithms it contains:

  • Full Windows Vista / Windows 7 UAC support
  • Ability for limited users to check and then update if they have credentials
  • Support for wonky corporate inernet. (If you've ever worked with a corporation this is a real problem).
  • Quick extracting, patching, and installing of files.
  • Registry support.
  • Roll back files & registry on error or cancellation by the user
  • Self-update (no files left behind)

We also have the file specifications here.

Automatic updating

Since being automatic is a requirement let me tell you how we do it with our AutomaticUpdater control.

We use named pipes to communicate between the standalone updater (wyUpdate) and the Automatic Updater control sitting on your program's form. wyUpdate reports progress to the Automatic Updater, and the Automatic Updater can tell wyUpdate to cancel progress, to start downloading, start extracting, etc.

This keeps the updater separate from your application.

In fact, the exact named pipes C# code we use is included in an article I wrote a little while back: Multi-process C# app like Google Chrome.

Wyatt O'Day
  • 1,893
  • 1
  • 28
  • 29
  • 2
    I can vouch for wyBuild and wyUpdate being an excellent product. It's much more flexible than ClickOnce, and it's extremely affordable -- one important aspect of software engineering is to know when to buy and when to build, and for me, this was a clear decision to buy. – Mark Rushakoff Jun 08 '10 at 23:06
  • 1
    looking over these products, they look fantastic. i can only hope i can use them some day. :) – Jake Berger Feb 06 '12 at 18:00
  • We offer free licenses for open source projects and school-sponsored student projects. See: http://wyday.com/wybuild/buy/special-prices.php – Wyatt O'Day Feb 06 '12 at 20:58
10

If you want your app to be updated automatically from a website and handle the code by yourself do the following steps:

  1. Create an XML file with a unique name for example help.xml and build a structure to specify the list of files to be updated in specific directories and version and etc. Then upload them on your website.

  2. App after connecting to website downloads this help.xml file and reads the content to make sure there are any new files (update files) on the website...

  3. If a new version of files was existed so start downloading from URL specified in help.xml file!

Jalal
  • 6,594
  • 9
  • 63
  • 100
4

Other answers look great.

However, if you're looking to hand-roll your own for whatever reason, simply put an XML file with information you need for your update process (e.g. description and version number of currently available version) somewhere on a webserver and use an HttpWebRequest (or HttpWebClient?) to download this file and process like you would any XML.

I use this simple method in peSHIr Tweets and it works great. Just update this file after you put a new version online for download and your update check will find it. Anything about this process is changeable the way you like, as you wrote it yourself.

Unless this is a private project for your own amusement/use/learning - like in my case - do look if anything already available suits your needs though!

peSHIr
  • 6,279
  • 1
  • 34
  • 46
  • If there are large number of users requesting the same file eg:100 users running the program,on startup 100 requests(version check)are send by each program.Will this hang a standard shared hosting server? – techno Oct 13 '13 at 11:35
  • Like I wrote: for simple stuff you can write it yourself. This also means you have to think about it yourself what could go wrong, what you want to happen in that case and if you want to take provisions for that. I'm only telling you what I used in my niche app that a few hunderd users.. – peSHIr Oct 19 '13 at 10:18
1

Take a look: Update Checker, I have wrote it to show the easy way to implement this feature in C#.

This XML file manages the updates:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<myCoolApp>
    <currentVersion>
        <major>9</major>
        <minor>1</minor>
        <build>5</build>
    </currentVersion>
    <path>http://TestApp.exe</path>
</myCoolApp>

The main funtion Check4Update() reads the XML file and parse it:

XmlDocument oDom = new XmlDocument();
oDom.Load(_sXmlConfig);

string str = oDom.SelectSingleNode("//currentVersion/major").InnerText;
Int32.TryParse(str, out _nMajor);

str = oDom.SelectSingleNode("//currentVersion/minor").InnerText;
Int32.TryParse(str, out _nMinor);

str = oDom.SelectSingleNode("//currentVersion/build").InnerText;
Int32.TryParse(str, out _nBuild); 

_sNewVersionPath = oDom.SelectSingleNode("//path").InnerText;
Leo Chapiro
  • 13,678
  • 8
  • 61
  • 92
  • Very clean and simple to use. Note: it does not download and install the app automatically, which is nice to give clients the option. – Jonas Jul 02 '22 at 17:46
0

Adding an update feature to your app is as simple as a walk in the park. Follow these steps and I'm sure you'll achieve it.

  1. Create a regular text file containing the new version of your app and the full direct download link of your app, then upload the text file to your server. Here's an example of how the text file should look like:

    1.2.0.0=http://www.yourserver.com/yourapp/update/appname_v1-2-0-0.exe
    
  2. Add a variable to your form where you will store the update download link

    private string download_link = null;
    
  3. Create a function to check for updates.

    public string CheckForUpdates()
    {
        /* Direct download link for the text file in your server */
        var version_file = "http://www.yourserver.com/appname/update/version.txt";
    
        /* Temporary output file to work with (located in AppData)*/
        var temp_version_file = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\appname_version.txt";
    
        /* Use the WebClient class to download the file from your server */
        using (var webClient = new WebClient())
        {
            try
            {
                webClient.DownloadFile(address: version_file, fileName: temp_version_file);
            }
            catch (Exception)
            {
                /* Handle exceptions */
                return "error";
            }
        }
    
        /* Check if temporary file was downloaded of not */
        if (File.Exists(temp_version_file))
        {
            /* Get the file content and split it in two */
            string[] version_data = File.ReadAllText(temp_version_file).Split('=');
    
            /* Variable to store the app new version */
            string version = version_data[0];
    
            /* Store the download link in the global variable already created */
            download_link = version_data[1];
    
            /* Compare the app current version with the version from the downloaded file */
            if (Application.ProductVersion.ToString() == version)
            {
                return "updated";
            }
            else
            {
                return "needs_update";
            }
        }
    
        /* Delete the temporary file after using it */
        if (File.Exists(temp_version_file))
        {
             File.Delete(temp_version_file);
        }
    }
    
  4. Create another function to perform the check (use of async-await)

    public async void RunUpdateCheck()
    {
        /* Maybe show a message to the user */
        labelUpdateState.Text = "Checking for updates. Please wait...";
    
        /* Variable to get the result from the check function */
        string result = await Task.Run(() => CheckForUpdates());
    
        /* Evaluate the result */
        switch (result)
        {
            case "error":
                /* Do something here, maybe just notify the user */
                break;
    
            case "updated":
                /* Do something here, maybe just notify the user */
                break;
    
            case "needs_update":
                /* Perform the update operation, maybe just download
                *  the new version with any installed browser or 
                *  implement a download function with progressbar 
                *  and the like, that's your choice.
                *
                *  Example:
                */
                Process.Start(download_link);
                break;
        }
    
        /* (Optional)
        *  Set the 'download_link' variable to null for future use. 
        */
        download_link = null;
    
        /* (Optional - in case you have a backup feature)
        *  Tell the user to backup any data that may be saved before installing
        *  the new version in case the data is stored in the app install folder,
        *  I recommend using the AppData folder for saving user data.
        */
        labelUpdateState.Text = "Please backup your data before installing the new version";
    }
    

I developed this method for myself and has worked perfectly. All you have to do is that every time you update your app you need to edit the text file in your server, change the app version to the new one. And, if required, change the download link.

I hope this helps like it helped me. Happy coding, guys!