<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>MillieSoft Blog &#187; mcml</title>
	<atom:link href="http://blog.milliesoft.co.uk/tag/mcml/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.milliesoft.co.uk</link>
	<description>Blogging about Media Center development</description>
	<lastBuildDate>Mon, 14 Jun 2010 09:16:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Code based dialogs in media center</title>
		<link>http://blog.milliesoft.co.uk/2010/03/code-based-dialogs-in-media-center/</link>
		<comments>http://blog.milliesoft.co.uk/2010/03/code-based-dialogs-in-media-center/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 08:50:09 +0000</pubDate>
		<dc:creator>Martin Millmore</dc:creator>
				<category><![CDATA[Media Center]]></category>
		<category><![CDATA[dialog]]></category>
		<category><![CDATA[mcml]]></category>

		<guid isPermaLink="false">http://blog.milliesoft.co.uk/?p=216</guid>
		<description><![CDATA[I&#8217;ve 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. Suppose though you want to do it all from within code, not within mcml. Why would you want to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve written a few posts on how to implement dialog boxes in media center (<a href="http://blog.milliesoft.co.uk/2009/02/adding-a-version-checker/">Adding a version checker</a> and <a href="http://blog.milliesoft.co.uk/2009/04/simpler-popup-dialog/">Simpler popup dialog</a>). They are both great examples of how to trigger a dialog box in mcml. Suppose though you want to do it all from within code, not within mcml. Why would you want to do that? Well, for one it means not having any AddIn calls in your mcml, and AddIn calls mean you can&#8217;t use the mcml preview tool &#8211; which significantly hampers development. For this example, I&#8217;m going to repeat the <a href="http://blog.milliesoft.co.uk/2009/02/adding-a-version-checker/">Adding a version checker</a> example, but all in code.</p>
<p>So, to trigger a dialog from your code, the first thing you need to do is to build some buttons;</p>
<pre><code>ArrayListDataSet dialogButtons = new ArrayListDataSet();
dialogButtons.Add("Download Now");
dialogButtons.Add("Remind me later");
dialogButtons.Add("Ignore");</code></pre>
<p>This adds 3 buttons to the dialog. Obviously add as many or as few as you like. The next thing you need to do is to add the call to open the dialog;</p>
<pre><code>String dialogText="There is a new version available";
String dialogTitle="New Version";
Microsoft.MediaCenter.Hosting.AddInHost.Current
.MediaCenterEnvironment.Dialog(dialogText</code></pre>
<pre><code>, "dialogTitle, dialogButtons, 30, true, null
, new Microsoft.MediaCenter.DialogClosedCallback(versionCallback));
</code></pre>
<p><code> </code></p>
<p>This will open a dialog as a modal dialog with a timeout of 30 seconds. When it is closed, the method <span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">versionCallback <span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px;">will be called, so now we need to write that method;</span></span></p>
<pre><code>public void versionCallback(Microsoft.MediaCenter.DialogResult result)
{
    if (result.ToString() == "100")
    {
        InstallNewVersion();
    }
    if (result.ToString() == "101")
    {
        RemindLater();
    }
    if (result.ToString() == "102")
    {
        IgnoreNewVersion();
    }
}</code></pre>
<p><code> </code></p>
<p>And obviously fill in the appropriate actions for each method.</p>
<p>Finally, you may want to block this dialog from triggering when you are in the debugger (since it won&#8217;t work), so put an if statement round it to stop it running in debug mode;</p>
<pre><code>#if(!DEBUG)
<span style="color: #808080;">   String dialogText="There is a new version available";
   String dialogTitle="New Version";
   Microsoft.MediaCenter.Hosting.AddInHost.Current
.MediaCenterEnvironment.Dialog(dialogText
  , "dialogTitle, dialogButtons, 30, true, null
  , new Microsoft.MediaCenter.DialogClosedCallback(versionCallback));</span></code></pre>
<pre><code>#endif
</code></pre>
<p><code> </code></p>
<p>And that&#8217;s it &#8211; an mcml dialog operated entirely from your code.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milliesoft.co.uk/2010/03/code-based-dialogs-in-media-center/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simpler popup dialog</title>
		<link>http://blog.milliesoft.co.uk/2009/04/simpler-popup-dialog/</link>
		<comments>http://blog.milliesoft.co.uk/2009/04/simpler-popup-dialog/#comments</comments>
		<pubDate>Sun, 19 Apr 2009 22:42:31 +0000</pubDate>
		<dc:creator>Martin Millmore</dc:creator>
				<category><![CDATA[Media Center]]></category>
		<category><![CDATA[dialog]]></category>
		<category><![CDATA[mcml]]></category>

		<guid isPermaLink="false">http://blog.milliesoft.co.uk/?p=105</guid>
		<description><![CDATA[In 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 also a simpler version of the Dialog if you don&#8217;t need to know anything about the response, e.g. if you are simply showing an information message. [...]]]></description>
			<content:encoded><![CDATA[<p>In a previous post on adding a <a href="http://blog.milliesoft.co.uk/2009/02/adding-a-version-checker/">version checker</a> to media center, I gave an example of how to write a popup dialog box for media center. There is also a simpler version of the <a href="http://msdn.microsoft.com/en-us/library/ms814612.aspx" target="_blank">Dialog</a> if you don&#8217;t need to know anything about the response, e.g. if you are simply showing an information message. This simpler version doesn&#8217;t require a callback to be defined, or any complex button definitions. It just needs a title, some text, a button name, a timeout and whether or not it is modal. Here&#8217;s an example;</p>
<pre><code>      &lt;Condition Source="[Preferences.TwitDialog]" SourceValue="true" ConditionOp="ChangedTo"&gt;
        &lt;Actions&gt;
          &lt;Set Target="[Preferences.TwitDialog]" Value="false"/&gt;
          &lt;Invoke Target="[AddInHost.MediaCenterEnvironment.Dialog]"
                  caption="Authorize Twitter"
                  text="Please authorize twitter."
                  buttons="Ok"
                  timeout="15"
                  isModal="true"/&gt;

        &lt;/Actions&gt;
      &lt;/Condition&gt;</code></pre>
<p>The buttons can only be ones from the list described in the <a href="http://msdn.microsoft.com/en-us/library/ms814612.aspx" target="_blank">documentation</a>. A modal window requires either the user or a timeout to close it before any other actions can be done, whereas a modeless window allows the user to continue with other things in the meanwhile.</p>
<p>The dialog is fired in this example by a property which is set in the code to true, and then set back to false when it is read. The condition only fires when the value is set to true in the first place by using the ConditionOp.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milliesoft.co.uk/2009/04/simpler-popup-dialog/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Front End and Back End Synchronization in MCML</title>
		<link>http://blog.milliesoft.co.uk/2009/04/front-end-and-back-end-synchronization-in-mcml/</link>
		<comments>http://blog.milliesoft.co.uk/2009/04/front-end-and-back-end-synchronization-in-mcml/#comments</comments>
		<pubDate>Sun, 19 Apr 2009 22:28:09 +0000</pubDate>
		<dc:creator>Martin Millmore</dc:creator>
				<category><![CDATA[Media Center]]></category>
		<category><![CDATA[data binding]]></category>
		<category><![CDATA[mcml]]></category>

		<guid isPermaLink="false">http://blog.milliesoft.co.uk/?p=86</guid>
		<description><![CDATA[One of the issues that has been hardest for me to learn with developing media center applications as been the linking of front end items in the MCML layer with data that I have in c# on the back end. For a long time I struggled with binding values from the code in to front [...]]]></description>
			<content:encoded><![CDATA[<p>One of the issues that has been hardest for me to learn with developing media center applications as been the linking of front end items in the MCML layer with data that I have in c# on the back end. For a long time I struggled with binding values from the code in to front end, and making method calls from the front end in to the back end. I suspect that the reason I did this was because that is how it is shown in the Media Center SDK and documentation, so I thought it was the only way.</p>
<p>It turns out that the SDK is in fact showing the most complicated use case. There is a much easier way of linking the front end and the back end, that is so simple compared to the rest of MCML development that it&#8217;s almost non-intuitive. The technique is to create a UI item in your C# code, and then refer to that item on the front end. You don&#8217;t have two items, one front end and one back end. Instead you simply have one item that is referenced in both layers. That means that when you make a change to the value of the item in your C# code, the change is instantly reflected in the UI, and when you make a change to the value of the item in the UI, the C# code can reference that value instantly. Because it is the same physical item in memory.<span id="more-86"></span>You can do this with any item that is a <a href="http://msdn.microsoft.com/en-us/library/bb188939.aspx" target="_blank">ModelItem</a>. This includes Choice, BooleanChoice, Command, InvokeCommand, NavigateCommand, EditableText, ListDataSet, RangedValue, ByteRangedValue, IntRangedValue, Timer, PropertySet, and of course anything which you construct yourself which implements ModelItem. That covers a fair bit of the things you may wish to put on the page in Media Center.</p>
<p>One issue that I have found is that you simply declare a public object in your class, you can&#8217;t access it in the UI. If you expose the same object via an accessor, it works fine. I don&#8217;t know why, but sticking to that rule works fine for me. Here&#8217;s an example of some of them in action;</p>
<pre><code>using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.MediaCenter.UI;

namespace TunerFreeMCE
{
    public class PreferencesUI :ModelItem
    {
        private BooleanChoice _getBBC;
        private Choice _frequency;
        private EditableText _goUSCommand;
        private Image _twitLogo;
        private bool _twitButton1Visbility = true;
        private string _twitText;

        public PreferencesUI()
        {
            _getBBC = new BooleanChoice(this.Owner,"Get BBC");
            _frequency = new Choice(this.Owner, "Cache Frequency");
            _goUSCommand = new EditableText(this.Owner, "US VPN Command");
            ArrayListDataSet frequencyList = new ArrayListDataSet();
            frequencyList.Add("1 hour");
            frequencyList.Add("2 hours");
            frequencyList.Add("4 hours");
            frequencyList.Add("12 hours");
            frequencyList.Add("24 hours");
            _frequency.Options = frequencyList;
                _frequency.ChosenIndex = 0;
            _twitLogo = new Image("C:/Program Files/MillieSoft/TunerFreeMCE/Images/twitter_logo.png");
        }

        public BooleanChoice GetBBCValue
        {
            get
            {
                return _getBBC;
            }
            set
            {
                _getBBC = value;
            }

        }

        public Choice GetFrequency
        {
            get
            {
                return _frequency;

            }
            set
            {
                _frequency = value;
            }
        }

        public EditableText USCommand
        {
            get
            {
                return _goUSCommand;

            }
            set
            {
                _goUSCommand = value;
            }
        }

        public bool TwitButton1Visibility
        {
            set
            {
                _twitButton1Visbility = value;
                FirePropertyChanged("TwitButton1Visibility");
            }
            get
            {
                return _twitButton1Visbility;
            }
        }

        public string TwitText
        {
            get { return _twitDialog; }
            set
            {
                if (value != _twitText)
                {
                    _twitText = value;
                    FirePropertyChanged("TwitDialog");
                }
            }
        }

        public Image TwitterLogo
        {
            get
            {
                return _twitLogo;
            }
        }

    }
}</code></pre>
<p>And here&#8217;s the corresponding MCML. The standard sample buttons and spinners are ommited &#8211; you can get those from the SDK very easily;</p>
<pre><code>&lt;Mcml xmlns="http://schemas.microsoft.com/2006/mcml"
xmlns:cor="assembly://MSCorLib/System"
xmlns:a="assembly://TunerFreeMCE/TunerFreeMCE"
xmlns:addin="assembly://Microsoft.MediaCenter/Microsoft.MediaCenter.Hosting"
xmlns:mc="assembly://Microsoft.MediaCenter/Microsoft.MediaCenter"
xmlns:me="Me"&gt;

&lt;UI Name="Preferences"&gt;

    &lt;Locals&gt;
      &lt;a:PreferencesUI Name="Preferences"/&gt;
    &lt;/Locals&gt;
    &lt;Rules&gt;
      &lt;Binding Source="[Preferences.TwitButton1Visibility]" Target="[SetTwitterUsername.Visible]"/&gt;

    &lt;/Rules&gt;
    &lt;Content&gt;
      &lt;Panel Layout="Dock"&gt;
        &lt;Children&gt;
          &lt;Panel Layout="Dock" MaximumSize="0,80"&gt;

            &lt;LayoutInput&gt;
              &lt;DockLayoutInput Position="Top" Alignment="Near"/&gt;
            &lt;/LayoutInput&gt;
            &lt;Children&gt;
              &lt;Panel Layout="VerticalFlow"&gt;
                &lt;Children&gt;
                  &lt;!-- Title text. --&gt;
                  &lt;Text Name="Banner" Content="[Preferences.TwitText]" Color="White"
										  Font="Sergio UI,45" Margins="10,0,0,0"&gt;
                  &lt;/Text&gt;
                &lt;/Children&gt;
              &lt;/Panel&gt;
            &lt;/Children&gt;
          &lt;/Panel&gt;
                  &lt;Panel  Margins="20,0,0,0"&gt;
                    &lt;Layout&gt;
                      &lt;FlowLayout Orientation="Vertical" Spacing="10,10" StripAlignment="Near"/&gt;
                    &lt;/Layout&gt; 

                    &lt;Children&gt;
                          &lt;Panel Layout="VerticalFlow"&gt;
                            &lt;Children&gt;

                              &lt;Graphic Content="[Preferences.TwitterLogo]" Name="TwitterLogo" Margins="0,2,0,0"&gt;

                              &lt;me:SimpleButton Name="SetTwitterUsername" EnormoList="[EnormoList]"&gt;
                                &lt;Command&gt;
                                  &lt;InvokeCommand Description="Set Twitter Username" Target="[Preferences.launchTwitterURL]"/&gt;
                                &lt;/Command&gt;
                              &lt;/me:SimpleButton&gt;

                              &lt;me:SimpleCheckBox EnormoList="[EnormoList]"&gt;
                                &lt;Model&gt;
                                  &lt;BooleanChoice BooleanChoice="[Preferences.GetBBCValue]"/&gt;
                                &lt;/Model&gt;
                              &lt;/me:SimpleCheckBox&gt;

                              &lt;me:SimpleSpinner EnormoList="[EnormoList]"&gt;
                                &lt;Model&gt;
                                  &lt;Choice Choice="[Preferences.GetFrequency]"/&gt;
                                &lt;/Model&gt;
                              &lt;/me:SimpleSpinner&gt;

                              &lt;me:SimpleEditBox EnormoList="[EnormoList]"&gt;
                                &lt;EditableText&gt;
                                  &lt;EditableText EditableText="[Preferences.USCommand]"/&gt;
                                &lt;/EditableText&gt;
                              &lt;/me:SimpleEditBox&gt;

                            &lt;/Children&gt;
                          &lt;/Panel&gt;

                    &lt;/Children&gt;
                  &lt;/Panel&gt;
        &lt;/Children&gt;
      &lt;/Panel&gt;
    &lt;/Content&gt;

  &lt;/UI&gt;
</code></pre>
<p>As you can see, the BooleanChoice is rendered as a checkbox on the page, the Choice as a spinner, the EditableText as a text box, the Image as a Graphic, the boolean is used to change the visibility of an item, and the string as display text. All of these items are defined in code and then referred to in the page, sometimes as a direct reference to the item, and sometimes as a property of another item.</p>
<p>This can be a complex lesson to get to grips with, but once you realize how this works, MCML programming becomes a whole lot easier.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milliesoft.co.uk/2009/04/front-end-and-back-end-synchronization-in-mcml/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flash in windows media center</title>
		<link>http://blog.milliesoft.co.uk/2009/02/flash-in-windows-media-center/</link>
		<comments>http://blog.milliesoft.co.uk/2009/02/flash-in-windows-media-center/#comments</comments>
		<pubDate>Fri, 13 Feb 2009 09:41:46 +0000</pubDate>
		<dc:creator>Martin Millmore</dc:creator>
				<category><![CDATA[Media Center]]></category>
		<category><![CDATA[Windows 7]]></category>
		<category><![CDATA[Add new tag]]></category>
		<category><![CDATA[BBC]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[mcml]]></category>
		<category><![CDATA[TunerFreeMCE]]></category>

		<guid isPermaLink="false">http://blog.milliesoft.co.uk/?p=73</guid>
		<description><![CDATA[Since my TunerFreeMCE code has been out there for almost a year now, I have picked up a fair bit of experience of playing flash on windows media center. Most of the TV companies who provide flash video do so using the Akamai tech stack to secure and stream their content. They build their own [...]]]></description>
			<content:encoded><![CDATA[<p>Since my <a href="http://www.milliesoft.co.uk/index.php?option=com_content&amp;view=article&amp;id=9:iplayer-mce&amp;catid=1:software&amp;Itemid=11" target="_blank">TunerFreeMCE</a> code has been out there for almost a year now, I have picked up a fair bit of experience of playing flash on windows media center.</p>
<p>Most of the TV companies who provide flash video do so using the Akamai tech stack to secure and stream their content. They build their own custom flash players on top of that to provide their own flavour to the players, e.g. related videos and so on. The probably intentional side effect of this is that it is really not trivial to get in to their flash streams and do anything with it. It&#8217;s not like the have an rtmp url easily accessible for you to get hold of. There are ways of doing it, but not easily. There is for example a project on sourceforge called rtmpdump (<a href="http://sourceforge.net/projects/rtmpdump/">http://sourceforge.net/projects/rtmpdump/</a>) which allows you to download flash videos from the BBC and from Hulu.<span id="more-73"></span>One of the biggest problems with the TV companies building their own flash players is that they typically don&#8217;t build them to interact with the remote control &#8211; i.e. they don&#8217;t listen for key presses, or have useful javascript hooks to send messages to the player. I have at times overcome that in the past by building custom versions of the flash players. That&#8217;s time consuming and annoying.</p>
<p>Another annoyance with flash is that it is not supported in MCML &#8211; the vista and windows 7 presentation layer for writing media center applications. That means that any application like this has to exit MCML and enter html to play flash content. That&#8217;s not that hard to build, but it does have the additional pain that you can&#8217;t use the MCMLPad debugger with the code any more, because it&#8217;s not compatible with the Add-In required to go to html. Doesn&#8217;t effect the end user, but is a pain for the developer.</p>
<p>A further annoyance is Flash&#8217;s full screen behaviour. For some security reason, they don&#8217;t allow any mouse or keyboard input to be received by the flash player when in full screen, except the escape key. Probably to avoid someone creating a fake version of your PC and tricking you in to doing things, but its much more of a pain than a benefit in my opinion. That means that to pick up remote event, you need to exit full screen. You could just have a large flash window to work round that, but flash add some hardware acceleration in full screen mode that you miss out on with just a large flash player.</p>
<p>The really big problem with flash though is extenders. The way that extenders work is that they have one dedicated channel for music and video, and everything else is sent via a remote desktop connection. Microsoft have a great article on it here;</p>
<p><a href="http://msdn.microsoft.com/en-us/library/bb852206.aspx">http://msdn.microsoft.com/en-us/library/bb852206.aspx</a></p>
<p>To summarize it though, you will get WMV, MPEG-1, MPEG-2, WMA, MP3 and WAV-PCM to play fine on an extender, and everything else is routed over the remote desktop protocol, which has quite a few limitations. Most notable of those limitations is that the frame rate is poor, and in some cases no sound (I have never worked out why no sound &#8211; if anyone knows the explanation, I would love to know). Microsoft&#8217;s advice is not to use flash on extenders. It&#8217;s a shame they didn&#8217;t make a flash engine part of the technology requirements on the extender, but it&#8217;s too late for that now.</p>
<p>As part of the windows 7 beta testing, I grilled Microsoft on support for flash in the MCML layer and on extenders. Unfortunately the answer is that they don&#8217;t see it as a priority at this time. I think that is very short sighted given the direction that online video is going. Over the past year, I have noticed more TV providers move away from WMV to flash, because it is cross-platform compatible. That gets the Mac and Linux lobbyists off their backs. I also suspect that the DRM on WMV being cracked didn&#8217;t endear that format to them either.</p>
<p>So, since the future of online video for the moment lies with flash, and Microsoft aren&#8217;t interested in providing better support for that in media center and extenders, the only real way of getting great support for online video in media center is for someone to write a transcoder for converting the flash stream to WMV or MPEG-1/2. Since the flash streams typically contain H.264 video for high def, simply unpacking it from the rtmp stream isn&#8217;t enough for it to play on extenders or pre-windows 7 media centers, since they don&#8217;t support that video format. That conversion is not a trivial thing to do on the fly (as opposed to downloading the whole thing first then converting it).</p>
<p>I am hoping that this mini-essay on the topic is going to prompt someone out there to start an open source project to convert flash streams to a media center compatible format. There are lots of add-ins that would benefit from it, like my <a href="http://www.milliesoft.co.uk/index.php?option=com_content&amp;view=article&amp;id=9:iplayer-mce&amp;catid=1:software&amp;Itemid=11" target="_blank">TunerFreeMCE</a> code, <a href="http://push-a-button.com/products/youglevista/" target="_blank">Yougle</a> and I&#8217;d imagine <a href="http://www.secondrun.tv/" target="_blank">SecondRun.tv</a> when it gets release, so go on someone, make a name for yourself by taking up this challenge.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milliesoft.co.uk/2009/02/flash-in-windows-media-center/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Adding a version checker &#8211; code walkthrough</title>
		<link>http://blog.milliesoft.co.uk/2009/02/adding-a-version-checker/</link>
		<comments>http://blog.milliesoft.co.uk/2009/02/adding-a-version-checker/#comments</comments>
		<pubDate>Mon, 02 Feb 2009 12:28:04 +0000</pubDate>
		<dc:creator>Martin Millmore</dc:creator>
				<category><![CDATA[Media Center]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[mcml]]></category>

		<guid isPermaLink="false">http://www.milliesoft.co.uk/blog/?p=7</guid>
		<description><![CDATA[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&#8217;s one of the big features that was missing from my TunerFreeMCE application. It also made me [...]]]></description>
			<content:encoded><![CDATA[<p>I was reading an article today on <a href="http://www.symbian-guru.com/welcome/2009/01/s60-developers-doing-things-right.html" target="_blank">Symbian Guru</a> 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&#8217;s one of the big features that was missing from my TunerFreeMCE application. It also made me realize that I didn&#8217;t know what the best practice was for things like that, so I googled &#8220;c# check for new program version&#8221; and frankly what came back was irrelevant or overly complex. I had some very simple requirements;</p>
<ul>
<li>Minimal web traffic &#8211; I pay for this hosting you know!</li>
<li>Minimal application impact</li>
<li>Easy for the user</li>
</ul>
<p><span id="more-7"></span>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 &#8220;2.1.0&#8243; 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&#8217;s code checking the version, which I hope isn&#8217;t going to cause problems. The last thing I want is performance to suffer just because of an automated checker. It&#8217;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.</p>
<h2>Getting the latest version and the current version</h2>
<p>Here&#8217;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#.</p>
<blockquote><p><code>using System.Reflection;<br />
using System.Web;<br />
using System.Net;<br />
...</code></p>
<p>/** Get the version of TunerFreeMCE from the assembly store*/</p>
<p>public string getCurrentVersionNumber()<br />
{<br />
Assembly execAssembly = typeof(TunerFreeMCE.MyAddIn).Assembly;</p>
<p>AssemblyName name = execAssembly.GetName();</p>
<p>// format the name in a human readable format.</p>
<p>string s1 = (string.Format(&#8220;{0}.{1:0}.{2:0}&#8221;,<br />
name.Version.Major.ToString(),<br />
name.Version.Minor.ToString(),<br />
name.Version.Build.ToString()<br />
));<br />
return s1;<br />
}</p>
<p>/** method to get the contents of a web page*/</p>
<p>private string getWebPage(string url)<br />
{<br />
string result = &#8220;&#8221;;</p>
<p>// don&#8217;t want any errors raised out of this, so throw away everything in a try-catch block<br />
try<br />
{<br />
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);<br />
myRequest.UserAgent = &#8220;Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)&#8221;;</p>
<p>myRequest.Method = &#8220;GET&#8221;;<br />
// create a cookie container in case we need to read the cookies</p>
<p>CookieContainer c1 = new CookieContainer();<br />
myRequest.CookieContainer = c1;<br />
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();<br />
StreamReader sr = new StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.UTF8);<br />
result = sr.ReadToEnd();<br />
sr.Close();<br />
}<br />
catch (Exception e) { }<br />
return result;<br />
}</p>
<p>/** Method to get the latest version number publicised */</p>
<p>public string getLatestVersion()<br />
{<br />
string latestVersion = getWebPage(&#8220;http://www.milliesoft.co.uk/current_version&#8221;).Trim();<br />
return latestVersion;<br />
}</p></blockquote>
<h2>Triggering the dialog in MCML</h2>
<p>Once I&#8217;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;</p>
<blockquote><p><code>/**method to check the versions of the code */<br />
public void checkNewVersion(){<br />
// don't check if a delayed reminder has been set<br />
if (DateTime.Now.Date &gt;= prefs.remindDate)<br />
{<br />
string latestVersion = prefs.getLatestVersion();<br />
// if we are ignoring this version don't do anything<br />
if (prefs.getCurrentVersionNumber() != latestVersion &amp;&amp; prefs.ignoreVersion != latestVersion)<br />
{<br />
// we aren't running the latest version, so set the message string and set the property to display the dialog.<br />
_newVersionString = "You are currently running version " + prefs.getCurrentVersionNumber() + " of TunerFree MCE. Version " + latestVersion + " is now available";<br />
NewVersionDialog = "true";<br />
}<br />
}<br />
}<br />
/** method to set the value of the property to look for when poping the dialog */<br />
public string NewVersionDialog<br />
{<br />
get { return _newVersionDialog; }<br />
set<br />
{<br />
if (value != _newVersionDialog)<br />
{<br />
_newVersionDialog = value;<br />
FirePropertyChanged("NewVersionDialog");<br />
}<br />
}<br />
}</code></p>
<p>/** method to record that we are ignoring this version */<br />
public void IgnoreNewVersion()<br />
{<br />
prefs.ignoreVersion = prefs.getLatestVersion();<br />
prefs.savePreferences();<br />
}</p>
<p>/** method to record that we want to be reminded in one day about this version */<br />
public void RemindLater()<br />
{<br />
prefs.remindDate = DateTime.Now.AddDays(1);<br />
prefs.savePreferences();<br />
}</p>
<p>/** method to get the string for the new version dialog */<br />
public string NewVersionString<br />
{<br />
get<br />
{<br />
return _newVersionString;<br />
}<br />
}</p></blockquote>
<h2>Displaying the dialog in MCML</h2>
<p>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.</p>
<blockquote><p><code>&lt;Locals&gt;</code></p>
<p>&lt;addin:AddInHost Name=&#8221;AddInHost&#8221;/&gt;<br />
&lt;mc:DialogResultHandler Name=&#8221;ResultHandler&#8221;/&gt;<br />
&lt;ArrayListDataSet Name=&#8221;DialogButtons&#8221;&gt;<br />
&lt;Source&gt;<br />
&lt;cor:String cor:String=&#8221;Download&#8221;/&gt;<br />
&lt;cor:String cor:String=&#8221;Remind me later&#8221;/&gt;<br />
&lt;cor:String cor:String=&#8221;Ignore&#8221;/&gt;<br />
&lt;/Source&gt;<br />
&lt;/ArrayListDataSet&gt;<br />
&lt;mc:PageId Name=&#8221;PageId&#8221; PageId=&#8221;ExtensibilityUrl&#8221;/&gt;<br />
&lt;/Locals&gt;</p>
<p>&lt;Rules&gt;</p>
<p>&lt;!&#8211; when the NewVersionDialog property is set to true, show this dialog &#8211;&gt;</p>
<p>&lt;Condition Source=&#8221;[EnormoList.NewVersionDialog]&#8221; SourceValue=&#8221;true&#8221;&gt;<br />
&lt;Actions&gt;<br />
&lt;Set Target=&#8221;[EnormoList.NewVersionDialog]&#8221; Value=&#8221;false&#8221;/&gt;<br />
&lt;Invoke Target=&#8221;[AddInHost.MediaCenterEnvironment.Dialog]&#8221;<br />
caption=&#8221;New Version&#8221;<br />
text=&#8221;[EnormoList.NewVersionString]&#8221;<br />
buttons=&#8221;[DialogButtons]&#8221;<br />
timeout=&#8221;30&#8243;<br />
isModal=&#8221;true&#8221;<br />
imagePath=&#8221;null&#8221;<br />
callback=&#8221;[ResultHandler.Callback]&#8220;/&gt;</p>
<p>&lt;/Actions&gt;<br />
&lt;/Condition&gt;</p>
<p>&lt;!&#8211; check for the results from the dialog. If 100 (the first button), navigate to the site to download the new version &#8211;&gt;<br />
&lt;Changed Source=&#8221;[ResultHandler.DialogDismissed]&#8220;&gt;<br />
&lt;Conditions&gt;<br />
&lt;Equality Source=&#8221;[ResultHandler.Result.ToString]&#8221; Value=&#8221;100&#8243;/&gt;<br />
&lt;/Conditions&gt;<br />
&lt;Actions&gt;<br />
&lt;Invoke<br />
Target=&#8221;[AddInHost.MediaCenterEnvironment.NavigateToPage]&#8221;<br />
pageId=&#8221;[PageId]&#8220;&gt;<br />
&lt;pageParameters&gt;<br />
&lt;cor:String String=&#8221;http://www.milliesoft.co.uk/&#8221;/&gt;<br />
&lt;/pageParameters&gt;<br />
&lt;/Invoke&gt;<br />
&lt;/Actions&gt;<br />
&lt;/Changed&gt;<br />
&lt;!&#8211; if 101 (the second button), call the method to remind later &#8211;&gt;<br />
&lt;Changed Source=&#8221;[ResultHandler.DialogDismissed]&#8220;&gt;<br />
&lt;Conditions&gt;<br />
&lt;Equality Source=&#8221;[ResultHandler.Result.ToString]&#8221; Value=&#8221;101&#8243;/&gt;<br />
&lt;/Conditions&gt;<br />
&lt;Actions&gt;<br />
&lt;Invoke<br />
Target=&#8221;[EnormoList.RemindLater]&#8220;/&gt;<br />
&lt;/Actions&gt;<br />
&lt;/Changed&gt;</p>
<p>&lt;!&#8211; if 102 (the third button), call the method to ignore this version&#8211;&gt;<br />
&lt;Changed Source=&#8221;[ResultHandler.DialogDismissed]&#8220;&gt;<br />
&lt;Conditions&gt;<br />
&lt;Equality Source=&#8221;[ResultHandler.Result.ToString]&#8221; Value=&#8221;102&#8243;/&gt;<br />
&lt;/Conditions&gt;<br />
&lt;Actions&gt;<br />
&lt;Invoke<br />
Target=&#8221;[EnormoList.IgnoreNewVersion]&#8220;/&gt;<br />
&lt;/Actions&gt;<br />
&lt;/Changed&gt;</p>
<p>&lt;/Rules&gt;</p></blockquote>
<p>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&#8217;s a known issue that hopefully Microsoft are going to address in the Windows 7 version.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milliesoft.co.uk/2009/02/adding-a-version-checker/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
