Team SOAK wins Imagine Cup 2008

Well done to David Burela from Readify and the rest of the SOAK team for winning the Imagine Cup.

Read More:

http://www.smh.com.au/news/technology/aussies-beat-the-world-in-imagine-cup/2008/07/09/1215282896605.html

http://davidburela.wordpress.com/2008/05/22/2008-imagine-cup-australian-winner-project-soak/

http://apcmag.com/imagine_cups_surprise_winners_a_boon_for_farmers.htm

I only met David a couple of days before he left for Paris, when I joined Readify so I really can't give any insider knowledge other than the internal mailing lists have been buzzing about it for weeks now. Andrew has some more on his blog.

Posted by colin | 2 comment(s)
Filed under:

Life.Reset();

In about a week I'll be landing in Melbourne to take up a position with Readify. It sounds like a great place to work with a bunch of very skilled people. It will force me to jump in the deep end again and get on top of the latest Microsoft products.

Melbourne is a beautiful city and I think it's going to be a good place for me and my family to live. By all accounts the windsurfing is good there too!

Posted by colin | 6 comment(s)

Fluent Argument Validation

Roger Alsing has written some neat code for argument validation using fluent C# extension methods. Read the "How to validate a method’s arguments?" blog entry. Here's a sample taken from that blog entry.

public static void MyMethod(string someArg,int someOtherArg)
{
   someArg.RequireArgument("someArg")
          .NotNull()
          .ShorterThan(10)
          .StartsWith("Roger");

   someOtherArg.RequireArgument("someOtherArg")
               .InRange(10,100)
               .NotEqual(33)
               .NotEqual(51)
    //do stuff
}

He's also put together some of his other code into a mini-framework for download. The async fork is another another class worth taking a look at for a nice clean way to run asyncronous tasks.

Posted by colin | 1 comment(s)
Filed under:

Maps Addin Photos

Jorge Mozo was kind enough to send me some photos of the Google Maps Addin for Windows Media Center running on his big screen TV using an XBox 360 extender. I think it looks pretty cool!

Xbox360 GMAPS

He also has the new Moon and Mars maps addin installed.

GMOONGMARS 

Jorge has also been helping me to translate the instructions into Spanish.

Posted by colin | with no comments
Filed under:

Browse the Moon and Mars from your couch too

Untitled

Google introduced maps of the Moon and Mars a while ago, now you can access those maps using the JavaScript API. I've created Windows Media Center addins for those too in case you've run out of places to explore on earth.

Get the installs for GMAPMCE, GMOONMCE and GMARSMCE from http://savage.org.za/mediacenter.htm

Posted by colin | with no comments
Filed under:

WebUnitAsp 2 : An experiment in unit testing asp.net

After the dismal failure of WebUnitAsp (thanks to the 2 people that downloaded it and the 1 person that spammed the discussion group), I thought that I might have another go and address some of the shortcomings of the original. For those that don't know what it is, it's a testing library based around the NUnitAsp model of control testers for each of the asp.net built in controls (i.e. there's a ButtonTester for Buttons, PanelTester for Panels etc.) and uses browser automation to load the pages.

Download WebUnitAsp2.zip

The code above is really just a proof of concept and builds on some other applications and code.

WebServer.WebDev is the built in web server in Visual Studio 2005 so you'll need that to be able to run the tests. Not a big ask since I'm sure most people develop asp.net in Visual Studio. I have modified the original code slightly to allow me to point it at an existing directory and start a webserver there.

The latest release (2.0 CTP) from WatiN has support for Internet Explorer and Firefox automation. While asking Phil Haack for permission to use the webserver code above, he asked how it's different from WatiN; the answer is not much. Instead of duplicating the effort of browser automation, I have built this version on top of WatiN. For Firefox automation you'll need to install the JSSH plugin as detailed on the WatiN website.

The unit tests are written using NUnit but it is not necessary to use NUnit.

What all this allows you to do is to write tests like the code below:

[Test] public void SimpleTest() { using (TestWebServer webserver = new TestWebServer(12345, "/Foo", @"C:\WebUnitAsp.TestSite")) { Uri baseUri = webserver.Start(); string startPage = baseUri + "Buttons.aspx"; using (IBrowser browser = new FireFox(startPage)) { WebForm form = new WebForm(browser, webserver); ButtonTester disabled = new ButtonTester("_disabledButton", form); Assert.IsFalse(disabled.Enabled, "Button should be disabled"); } } }

Note that the webserver starts on the specified port and will compile any asp.net content in the specified directory, so in this case baseUri will be http://localhost:12345/Foo/ . Because the web server is started using managed code, you can then use a tool like NCover to obtain the code coverage of the unit tests on the server side asp.net code.

coverage

The "Tester" objects take care of resolving the content in the browser like a button inside a nested MasterPage has an ID of "_ctl0__ctl0_ContentPlaceHolder1_ContentPlaceHolder2_button" when the page runs with with <xhtmlConformance mode="Legacy"/> in the web.config and an ID of "ctl00_ctl00_ContentPlaceHolder1_ContentPlaceHolder2_button" when there is <xhtmlConformance mode="Strict"/> in web.config. There is an example of this in the download with the following test code:

string startPage = String.Format("{0}{1}", BaseUrl, "NestedMasterPageWebForm.aspx"); browser.GoTo(startPage); WebForm form = new WebForm(browser, this.WebServer); MasterPageTester master1 = new MasterPageTester(form); MasterPageTester master2 = new MasterPageTester(master1); ContentPlaceHolderTester content1 = new ContentPlaceHolderTester("ContentPlaceHolder1", master2); ContentPlaceHolderTester content2 = new ContentPlaceHolderTester("ContentPlaceHolder2", content1); ButtonTester button = new ButtonTester("button", content2); Assert.IsTrue(button.Visible, "Control Exists");

It is intended that from any Tester object, that you can also access the underlying html elements. It is quite a big stack of technologies, but I'd like to hear any ideas, criticism, problems etc.

Posted by colin | with no comments
Filed under:

I didn't know I could do that #5 : Send html form via email

Until now I thought the only way to send email from a web page was using a hyperlink and the mailto: syntax e.g.

<a href="mailto:name@example.org?subject=Rhubarb&amp;body=This is the body" >Send mail</a>

and the content of the email was limited to how much data you can fit into 2048 characters (the url length limit in IE).

However, today it occurred to me that instead of using the anchor tag <a>, to use a <form> tag and POST the data to the mailto address by submitting the form. Doh! it's so obvious now...

<form action="mailto:name@example.org?subject=rhubarb"" method="POST">
            <!-- input, hidden fields etc go here -->
            <input type="hidden" name="bigdata" value="some really long data" />
            <input type="submit" value="send mail" name="submit"/>
</form>

It works that way in IE at least, Firefox still has a size limit.

Posted by colin | with no comments
Filed under:

When the power goes out...

Since the rolling blackouts in ZA are here to stay for a while, here's a scrap of C# 2.0 code I wrote to notify me when the power goes out at my house. I have an old laptop that my Internet connection is plugged into, so it switches onto battery power but the wireless iburst connection stays connected. It runs as a windows service but I'll leave the basics of that to this article. In my case it sends an email but it could perform some other action.

using System; using System.ServiceProcess; using System.Net.Mail; using System.Windows.Forms; using System.Configuration; public partial class Battery : ServiceBase { private PowerLineStatus _status = PowerLineStatus.Unknown; private string _from, _to, _smtpHost; public Battery() { InitializeComponent(); } protected override void OnStart(string[] args) { PowerLineStatus _status = SystemInformation.PowerStatus.PowerLineStatus; _from = ConfigurationManager.AppSettings["from"]; _to = ConfigurationManager.AppSettings["to"]; _smtpHost = ConfigurationManager.AppSettings["smtp"]; } protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus) { PowerLineStatus newStatus = SystemInformation.PowerStatus.PowerLineStatus; if (powerStatus == PowerBroadcastStatus.PowerStatusChange && newStatus != _status) { _status = newStatus; MailMessage message = new MailMessage( _from, _to, String.Format("Power status is {0}", _status), DateTime.Now.ToString()); SmtpClient smtp = new SmtpClient(_smtpHost); smtp.Send(message); } return base.OnPowerEvent(powerStatus); } }

Perhaps combined with some GPS coordinates and an online map, a view of the current power state for the whole country could be possible?

Posted by colin | 1 comment(s)

Adding JScript.Net Scripting to C# Application

Download Code: CsJScriptDemo.zip 46KB

I didn't find much on the 'net when I was looking for ways to do this so here is my solution for adding basic scripting functionality to a C# application with an object model. This method uses CodeDOM to generate and compile a JScript.net class on the fly, using the classes and interfaces from the C# application. It uses .Net 2.0, and a Visual Studio 2005 solution is provided.

For the purposes of this exercise, I have a windows forms application as shown below. The application has a Listbox bound to a collection of items on the left, a Textbox to type scripts into on the right and a Button to execute the script.

jscsapp

For the object model I have 2 objects:

  1. Application has a Title property that changes the title of the main form, and a generic collection of Item objects which is bound to the list on the left.
  2. Item has a single property Text.

Jumping into the code, the Item and Application objects are shown below. Note that both objects inherit from JSObject to get the associative array behaviour that you would expect in javascript, but it is not required. The Application constructor has a reference to the Form object so that we can change the text.

public class Item:Microsoft.JScript.JSObject { private string _text; public Item(string text) { _text = text; } public string Text { get { return _text; } set { _text = value; } } } public class Application:Microsoft.JScript.JSObject { private Collection<Item> _items; private System.Windows.Forms.Form _form; internal Application(System.Windows.Forms.Form form) { _items = new Collection<Item>(); _form = form; } public Collection<Item> Items { get { return _items; } } public string Title { get { return _form.Text; } set { _form.Text = value; } } }

The main form has an instance of the Application object which will be passed to the script when it is executed.

private Savage.CsJScriptDemo.Model.Application _application; public Form1() { InitializeComponent(); _application = new Savage.CsJScriptDemo.Model.Application(this); UpdateList(); } private void UpdateList() { this._listBox.DataSource = null; this._listBox.DataSource = _application.Items; this._listBox.DisplayMember = "Text"; }

To execute the script I have a single method on an interface called ICompiledScript.Go which takes the Application instance. You can change this or add more methods that with different arguments and return types if you need to. The JScript will be compiled into a class that implements that interface, so that we don't need to use invoke to call the methods.

ICompiledScript compiled = ScriptCompiler.Compile(_scriptTextBox.Text); compiled.Go(_application); UpdateList();

I'll refer you to the source code attached for the entire ScriptCompiler class because CodeDOM is quite verbose as you can see from the fragment below:

//could easily be C# or VB CodeDomProvider codeProvider = new JScriptCodeProvider(); //Namespaces CodeNamespace codeNamespace = new CodeNamespace("some.arbitrary.name.space"); codeNamespace.Imports.Add(new CodeNamespaceImport("System")); codeNamespace.Imports.Add(new CodeNamespaceImport("Savage.CsJScriptDemo.Model")); //Scripting Class CodeTypeDeclaration codeTypeDecl = new CodeTypeDeclaration(className); codeTypeDecl.IsClass = true; codeTypeDecl.BaseTypes.Add(typeof(object)); codeTypeDecl.BaseTypes.Add(typeof(ICompiledScript)); codeNamespace.Types.Add(codeTypeDecl); //...snip

There are no special tricks in the ScriptCompiler class, it creates a class that implements ICompiledScript, adds a constructor and the Go method containing the script provided. The assembly is then compiled in memory and an instance of the class returned.

There are some quirks in this method that you'll need to experiment with for your application e.g.

The case of toString() is ToString() so either implement the other method or use a regex to replace the offending text before compiling the script.

You will run into code access security permissions at some point if you are accessing files or UI elements etc.

Your JScript class cannot inherit from a C# class but you can implement interfaces.

Because you are referencing the C# assembly, all the public classes exposed in that assembly are available to the JScript (if the user knows the namespaces) so be careful what you make available. You could also use regex to check for those kind of things before you compile.

Posted by colin | 1 comment(s)
Filed under: ,

WiX v3.0, LGHT0217 error and Light.exe unhandled exception on Vista

Here's 2 tips for developers using WiX 3.0 on Vista:

  1. If you are getting error MSB6006: "Light.exe" exited with code -532459699  or light.exe crashes with an unhandled exception and you are running v3.0.2925.0 or earlier build, get one of the later nightly builds from http://wix.sf.net/releases. I used v3.0.3307.0 and that fixed the problem.
  2. If you are getting this error: light.exe : error LGHT0217 : An unexpected external UI message was received: The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2738. I found the answer here, it turns out that vbscript.dll is not registered and some of the installer validations are written in vbscript. To fix the problem, open a command prompt as administrator, and run the following command:

C:\>regsvr32.exe C:\Windows\System32\vbscript.dll

Posted by colin | 1 comment(s)
Filed under:

He that fights and runs away...

On Thursday last week I was chatting to someone on instant messenger about the free ZaEpg service that I have been running, and the question of how long I planned to continue providing the service came up. I said that I had no intention to stop, but who knows what can happen in the future. Ironically the next day it happened.

For those that don't know, I was scraping the tv guide content from the dstv.com website and and supplying it to users in xmltv format for the Mediaportal, Mythtv and other HTPC users, the EPG format required for Windows Media Center, and in pdf. Originally I had written a scraper that anyone could use but that seemed to cause problems for the dstv website so it was removed in favour of one person downloading the epg and delivering it to the other users.

On Friday afternoon at 14:22 I received an emailed letter from multichoice's lawyers, demanding that I cease and desist publishing their copyrighted EPG and notify them within 48 hours of receiving the letter. Now I know you're all thinking : "That's a bit heavy handed, why didn't they just send an email instead of reaching for their lawyers?" and "That really is a strange time to send a letter and demand notice within 48 hours" and "Surely the people using the EPG are their subscribers?" and "Perhaps they think all the HTPC users will buy a multichoice PVR?".

To be fair, they are right that I was publishing the copyrighted info, and in accordance with the terms of their emailed letter, I have ceased and desisted. All the content was removed on Friday afternoon and they were notified via email at 17:33 on the same day. Furthermore I have no intention of continuing to provide to anyone the dstv EPG in any format whatsoever.

The approximately 1400 people using the various services: Since it was a free service, I have nothing to gain by getting into a legal scrap with multichoice. I am not going to provide the scraper software to assist dstv subscribers to download the epg from the dstv website, as I see no reason to support the people paying the company that is sending lawyers at me. It should be apparent how much multichoice cares about you. Perhaps your R440 could buy you a new dvd box set to watch every month, a computer game to play on those powerful HTPCs you have or maybe a few books to read instead.

If I can get the EPG data in electronic format from SABC and ETV, I'll restart the ZaEpg and xmltv services for those channels, so if anyone knows who to contact there, please let me know.

 

Technorati tags: , ,
Posted by colin | 44 comment(s)

Media Center Addin : Missed Skype Call Notification

I have a Skype dualphone plugged into my Windows Media Center because that's the PC that is online most of the time. I don't have a keyboard plugged into it because I prefer to control the whole thing with the remote only, and use the dualphone handset for Skype. To this end I have disabled as many notifications and popups as Skype will allow. There are two problems with running this arrangement:

  1. Without minimizing the media center full screen UI, I can't easily see if there are missed calls.
  2. Whenever I make an outgoing call with Skype, the Skype application grabs the window focus from media center, causing the remote to not work anymore, screensavers kick in while you're watching TV, the screen blanks while it changes mode ...just annoying things that shouldn't happen normally.

Originally I set out to solve both problems but after experimenting with the Skype api and setting "silent_mode" on, the api stops responding to requests about missed calls. i.e. Problem 2 is still a problem. I did however manage to solve problem 1 with this little addin.

Before you get too excited, it is not a full Skype client in media center like mcePhone, it only does notifications of missed calls and active incoming calls. However it is free and it does work on XP MCE and 32 bit Vista. I may add other notifications if necessary.

You can download the installer from here [download: SkypeInMce 1.0.0.0.zip]

 

Sidenote: This addin was developed using the free Sharpdevelop 2.2 IDE which has built in Wix support. I was really impressed by the progress the IC#Code team has made since the last time I looked at SD. Well done, it has become a very polished product. 

 

Technorati tags: ,
Posted by colin | with no comments

Vista Media Center EPG Discovery Service Hotfix

The epgStream people definitely have their ears closer to the ground than me.

If you occasionally get the "Invalid country or region" or "Unsupported country/region" error message in vista media center when it tries to download the epg from an alternate source like ZaEpg, then this is for you. To get media center to download the epg from another location, the registry key HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Media Center\Service\EPG\discSvc needs to point to the new url but media center resets it sometimes.

There is a hotfix KB935685 which allows you to prevent media center from resetting the registry key. There is no download link so you'll have to phone microsoft support to get it. Once the hotfix is installed you can set the registry key HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Media Center\Service\EPG\disableUpdateDiscSvc to 1

More details here  

After installing the hotfix and setting the registry keys, ZaEpg could be uninstalled and the registry keys should stay the same and ZaEpg continues to supply the epg to your media center

Technorati tags: ,
Posted by colin | with no comments

First Postcard

The Media Center EPG solution ZaEpg 1.1.0.0 is postcardware and after nearly 2 months and 300 users the first postcard arrived.

Thanks Clinton for sending the first postcard.

I'm extending the thanks to Brendon, Werner and Chris for picking up the ZaEpg bandwidth tab.

With some help from Craig there is now a 64bit version of ZaEpg available for download.

Posted by colin | with no comments

Duplicate Enum values

I discovered this feature of C# while changing Enum value names in one project, where the same enum is used in another project. I needed it to work for both the old and new names because the enum is used in xml serialization which writes the name rather than the value.


using System;
using System.Diagnostics;

enum Foo
{
    ValueA = 0,
    ValueC = 1,
    [Obsolete("Don't use this anymore")]
    ValueB = 1,
    ValueD = 2
}
class Program
{
    static void Main(string[] args)
    {
        Foo valA = Foo.ValueA;
        Foo valB = Foo.ValueB;
        Foo valC = Foo.ValueC;
        Foo valD = Foo.ValueD;
        
        Debug.WriteLine(valA.ToString(), "A");
        Debug.WriteLine(valB.ToString(), "B");
        Debug.WriteLine(valC.ToString(), "C");
        Debug.WriteLine(valD.ToString(), "D");
        
        Debug.Assert(valA != valB);
        Debug.Assert(valB == valC);
    }
}

 

Note that ValueB and ValueC have the same integer value, so the output of the program indicates that the order of the enum names is important.

A: ValueA
B: ValueC
C: ValueC
D: ValueD

You will get a compiler warning on Foo valB = Foo.ValueB; because of the Obsolete tag.

Posted by colin | with no comments
Filed under:
More Posts Next page »