Adding a version checker – code walkthrough

I was reading an article today on Symbian Guru about how more and more S60 developers are doing the right thing by including an automatic check for updates to their code. It guilted me in to realizing that it’s one of the big features that was missing from my TunerFreeMCE application. It also made me realize that I didn’t know what the best practice was for things like that, so I googled “c# check for new program version” and frankly what came back was irrelevant or overly complex. I had some very simple requirements;

  • Minimal web traffic – I pay for this hosting you know!
  • Minimal application impact
  • Easy for the user

In the end, I added a plain text file to my web site which has the latest file version in it, i.e. it just contains the text “2.1.0” at the moment. In my code, I just get that URL (http://www.milliesoft.co.uk/current_version if you must know), and compare it to the version from the assembly. Side effects of this are that my site is going to get a load of pings from everyone’s code checking the version, which I hope isn’t going to cause problems. The last thing I want is performance to suffer just because of an automated checker. It’ll be interesting to see how it does effect traffic, because the side effect of this is that I should get my first semi-accurate picture of how much my code is used.

Getting the latest version and the current version

Here’s some code snippets of how it was done, both making the web request, and getting the version number from the assembly store. All coding is in C#.

using System.Reflection;
using System.Web;
using System.Net;
...

/** Get the version of TunerFreeMCE from the assembly store*/

public string getCurrentVersionNumber()
{
Assembly execAssembly = typeof(TunerFreeMCE.MyAddIn).Assembly;

AssemblyName name = execAssembly.GetName();

// format the name in a human readable format.

string s1 = (string.Format(“{0}.{1:0}.{2:0}”,
name.Version.Major.ToString(),
name.Version.Minor.ToString(),
name.Version.Build.ToString()
));
return s1;
}

/** method to get the contents of a web page*/

private string getWebPage(string url)
{
string result = “”;

// don’t want any errors raised out of this, so throw away everything in a try-catch block
try
{
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
myRequest.UserAgent = “Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)”;

myRequest.Method = “GET”;
// create a cookie container in case we need to read the cookies

CookieContainer c1 = new CookieContainer();
myRequest.CookieContainer = c1;
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
StreamReader sr = new StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.UTF8);
result = sr.ReadToEnd();
sr.Close();
}
catch (Exception e) { }
return result;
}

/** Method to get the latest version number publicised */

public string getLatestVersion()
{
string latestVersion = getWebPage(“http://www.milliesoft.co.uk/current_version”).Trim();
return latestVersion;
}

Triggering the dialog in MCML

Once I’ve got the current version number and the latest version number, I need to do something with it, so I have the following in the code. checkNewVersion runs when my main code is initialized by the add-in;

/**method to check the versions of the code */
public void checkNewVersion(){
// don't check if a delayed reminder has been set
if (DateTime.Now.Date >= prefs.remindDate)
{
string latestVersion = prefs.getLatestVersion();
// if we are ignoring this version don't do anything
if (prefs.getCurrentVersionNumber() != latestVersion && prefs.ignoreVersion != latestVersion)
{
// we aren't running the latest version, so set the message string and set the property to display the dialog.
_newVersionString = "You are currently running version " + prefs.getCurrentVersionNumber() + " of TunerFree MCE. Version " + latestVersion + " is now available";
NewVersionDialog = "true";
}
}
}
/** method to set the value of the property to look for when poping the dialog */
public string NewVersionDialog
{
get { return _newVersionDialog; }
set
{
if (value != _newVersionDialog)
{
_newVersionDialog = value;
FirePropertyChanged("NewVersionDialog");
}
}
}

/** method to record that we are ignoring this version */
public void IgnoreNewVersion()
{
prefs.ignoreVersion = prefs.getLatestVersion();
prefs.savePreferences();
}

/** method to record that we want to be reminded in one day about this version */
public void RemindLater()
{
prefs.remindDate = DateTime.Now.AddDays(1);
prefs.savePreferences();
}

/** method to get the string for the new version dialog */
public string NewVersionString
{
get
{
return _newVersionString;
}
}

Displaying the dialog in MCML

and in the mcml page, to check for the new content and display the dialog, I need the following code. It sets up the buttons and a result handler for the dialog, and in the conditions looks for it to be fired, and listens for the response.

<Locals>

<addin:AddInHost Name=”AddInHost”/>
<mc:DialogResultHandler Name=”ResultHandler”/>
<ArrayListDataSet Name=”DialogButtons”>
<Source>
<cor:String cor:String=”Download”/>
<cor:String cor:String=”Remind me later”/>
<cor:String cor:String=”Ignore”/>
</Source>
</ArrayListDataSet>
<mc:PageId Name=”PageId” PageId=”ExtensibilityUrl”/>
</Locals>

<Rules>

<!– when the NewVersionDialog property is set to true, show this dialog –>

<Condition Source=”[EnormoList.NewVersionDialog]” SourceValue=”true”>
<Actions>
<Set Target=”[EnormoList.NewVersionDialog]” Value=”false”/>
<Invoke Target=”[AddInHost.MediaCenterEnvironment.Dialog]”
caption=”New Version”
text=”[EnormoList.NewVersionString]”
buttons=”[DialogButtons]”
timeout=”30″
isModal=”true”
imagePath=”null”
callback=”[ResultHandler.Callback]”/>

</Actions>
</Condition>

<!– check for the results from the dialog. If 100 (the first button), navigate to the site to download the new version –>
<Changed Source=”[ResultHandler.DialogDismissed]”>
<Conditions>
<Equality Source=”[ResultHandler.Result.ToString]” Value=”100″/>
</Conditions>
<Actions>
<Invoke
Target=”[AddInHost.MediaCenterEnvironment.NavigateToPage]”
pageId=”[PageId]”>
<pageParameters>
<cor:String String=”http://www.milliesoft.co.uk/”/>
</pageParameters>
</Invoke>
</Actions>
</Changed>
<!– if 101 (the second button), call the method to remind later –>
<Changed Source=”[ResultHandler.DialogDismissed]”>
<Conditions>
<Equality Source=”[ResultHandler.Result.ToString]” Value=”101″/>
</Conditions>
<Actions>
<Invoke
Target=”[EnormoList.RemindLater]”/>
</Actions>
</Changed>

<!– if 102 (the third button), call the method to ignore this version–>
<Changed Source=”[ResultHandler.DialogDismissed]”>
<Conditions>
<Equality Source=”[ResultHandler.Result.ToString]” Value=”102″/>
</Conditions>
<Actions>
<Invoke
Target=”[EnormoList.IgnoreNewVersion]”/>
</Actions>
</Changed>

</Rules>

The big down side of this code is that because it navigates to the web site to download the latest version, you have to use AddInHost, which unfortunately means that you can no longer debug the code in VisualStudio, because it bombs out as soon as the MCMLPad previewer sees that line. That’s a known issue that hopefully Microsoft are going to address in the Windows 7 version.

Tags: , ,

2 Responses to “Adding a version checker – code walkthrough”

  1. […] a previous post on adding a version checker to media center, I gave an example of how to write a popup dialog box for media center. There is […]

  2. […] written a few posts on how to implement dialog boxes in media center (Adding a version checker and Simpler popup dialog). They are both great examples of how to trigger a dialog box in mcml. […]

Leave a Reply