Code to check for updates, install new version of app
Asked Answered
F

3

13

I have a .NET 4 WPF app that gets installed using an MSI, generated via a visual studio setup project. Everything works great, except that I'm missing the Click Once Deployment feature that checks for new versions of the app on load and downloads/installs them. I switched away from Click Once Deployment because it seems to be a half-baked solution that makes you do hacks just to do simple things like have your app run on startup.

I was wondering if there is any sort of tutorial or code anyone can show me that lays out how to handle checking for new versions of the app, downloading the new version of the app, and installing the new app over the old one. This seems like something that most WPF apps would want to have, I'm surprised that I can't find anything about this on google.

Follett answered 5/2, 2011 at 14:39 Comment(0)
A
14

There is no such inbuilt or ready made tool. In startup of your application you can run your code which does following.

  1. Fetch your http://myserver.com/myproduct/update.xml, where you will keep settings of your latest version and url of a new update msi file
  2. If update is available that is different then the currently running version, then download the file using WebClient and store it in temp folder
  3. You can then create a batch file with following string and store it in temp folder
msiexec /u {your product code}
msiexec /i ..path to your new msi

Finally Execute your batch file using Process.Start and exit your app.

Asarum answered 5/2, 2011 at 18:7 Comment(1)
Thanks @Akash Kava I'm close now but see the issue I'm having below with the msiexec command line uninstall/install.Follett
F
17

Got it working, here is the code so that others don't need to reinvent the wheel...

public class VersionHelper
{
    private string MSIFilePath = Path.Combine(Environment.CurrentDirectory, "HoustersCrawler.msi");
    private string CmdFilePath = Path.Combine(Environment.CurrentDirectory, "Install.cmd");
    private string MsiUrl = String.Empty;

    public bool CheckForNewVersion()
    {
        MsiUrl = GetNewVersionUrl();
        return MsiUrl.Length > 0;
    }

    public void DownloadNewVersion()
    {
        DownloadNewVersion(MsiUrl);
        CreateCmdFile();
        RunCmdFile();
        ExitApplication();
    }

    private string GetNewVersionUrl()
    {
        var currentVersion = Convert.ToInt32(ConfigurationManager.AppSettings["Version"]);
        //get xml from url.
        var url = ConfigurationManager.AppSettings["VersionUrl"].ToString();
        var builder = new StringBuilder();
        using (var stringWriter = new StringWriter(builder))
        {
            using (var xmlReader = new XmlTextReader(url))
            {
                var doc = XDocument.Load(xmlReader);
                //get versions.
                var versions = from v in doc.Descendants("version")
                               select new
                               {
                                   Name = v.Element("name").Value,
                                   Number = Convert.ToInt32(v.Element("number").Value),
                                   URL = v.Element("url").Value,
                                   Date = Convert.ToDateTime(v.Element("date").Value)
                               };
                var version = versions.ToList()[0];
                //check if latest version newer than current version.
                if (version.Number > currentVersion)
                {
                    return version.URL;
                }
            }
        }
        return String.Empty;
    }

    private void DownloadNewVersion(string url)
    {
        //delete existing msi.
        if (File.Exists(MSIFilePath))
        {
            File.Delete(MSIFilePath);
        }
        //download new msi.
        using (var client = new WebClient())
        {
            client.DownloadFile(url, MSIFilePath);
        }
    }

    private void CreateCmdFile()
    {
        //check if file exists.
        if (File.Exists(CmdFilePath))
            File.Delete(CmdFilePath);
        //create new file.
        var fi = new FileInfo(CmdFilePath);
        var fileStream = fi.Create();
        fileStream.Close();
        //write commands to file.
        using (TextWriter writer = new StreamWriter(CmdFilePath))
        {
            writer.WriteLine(@"msiexec /i HoustersCrawler.msi /quiet");
        }
    }

    private void RunCmdFile()
    {//run command file to reinstall app.
        var p = new Process();
        p.StartInfo = new ProcessStartInfo("cmd.exe", "/c Install.cmd");
        p.StartInfo.CreateNoWindow = true;
        p.Start();
        //p.WaitForExit();
    }

    private void ExitApplication()
    {//exit the app.
        Application.Current.Shutdown();
    }
}
Follett answered 5/2, 2011 at 20:17 Comment(2)
really good answer. But better to check the version using msdn.microsoft.com/en-us/library/s3bf0xb2(v=vs.110).aspxGitlow
Code it inaccurate. You should remove 2 unused variables - StringBuilder builder, StringWriter stringWriter. Also, in funcs CreateCmdFile() and RunCmdFile() you should replace the hardcoded "HoustersCrawler.msi" and "Install.cmd" with already declared variables MSIFilePath and CmdFilePath. And also, both those paths should be quoted, like this: $"msiexec /i \"{MSIFilePath}\" /quiet"Implead
A
14

There is no such inbuilt or ready made tool. In startup of your application you can run your code which does following.

  1. Fetch your http://myserver.com/myproduct/update.xml, where you will keep settings of your latest version and url of a new update msi file
  2. If update is available that is different then the currently running version, then download the file using WebClient and store it in temp folder
  3. You can then create a batch file with following string and store it in temp folder
msiexec /u {your product code}
msiexec /i ..path to your new msi

Finally Execute your batch file using Process.Start and exit your app.

Asarum answered 5/2, 2011 at 18:7 Comment(1)
Thanks @Akash Kava I'm close now but see the issue I'm having below with the msiexec command line uninstall/install.Follett
W
2

Check out Scott Hanselman's blog post about manually update via clickonce.

Waggery answered 5/2, 2011 at 16:8 Comment(1)
Understood you're not using ClickOnce, however, my search brought me here and this will help others who are using CO: How to: Check for Application Updates Programmatically Using the ClickOnce Deployment API msdn.microsoft.com/en-us/library/ms404263.aspxQualmish

© 2022 - 2024 — McMap. All rights reserved.