Saturday 23 October 2010

Install the Full .Net 4 Framework with Tarma Installer

If you haven’t seen Tarma InstallMate before, the you need to check this little beauty out.  It’s a fully featured installer that  have been using it in production for just under a year now and the end-user setup installer just drops out of the end of my build process – sweet!

There’s one thing that is very different with Tarma and all the other installers out there – Tarma doesn’t charge stupid rip-off money like all the other suppliers seem to like to do.  You can get their top-of-the-range product for under $90USD per developer.  Couple that with totally superb support, rock solid performance and a really rich feature set, Tarma’s a total winner!

Out of the box, Tarma has support for a number of prerequisites like .Net Framework, Access runtimes and Windows Installer.  However, it doesn’t differentiate between the Full and Client Profiles for .Net 4 – if the Client Profile is detected then it will not install the full framework and I need to get the full framework onto my user’s machine. 

Detecting the Installed Framework Version

To detect which version of the .Net Framework 4 has been installed, you need to check the presence of the following registry keys.

HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client
HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full

More details on that here.

We can set up Tarma to do that easily, like this:

Read Registry Key into a Variable

Go to Symbolic Variables and add a new variable called IsFullDotnet4.  Then use Tarma’s support for symbolic expressions to read whether the registry key exists by setting the new variable’s value to this:

<$rkaccess(<HKLM>\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full)>

It should now look like this:

SNAGHTML6641ea8

Adjust Prerequisites Condition

Go to the prerequisites section and adjust the condition to install the .Net 4 Runtime by setting the condition to this:

NOT IsFullDotnet4

It should look something like this:

SNAGHTML7d171

That’s all you need – Tarma will now upgrade .Net 4 Client Profile installations to the Full version.

Monday 4 October 2010

Replacing Strings in XPObject.SetPropertyValue with Lambdas

I came across a post on Aussie Alf’s blog today about removing magic strings from the persistent property setters in the XPO ORM from DevExpress

The Aussie Alf blog is written by Michael Proctor who is a member of the DevExpress community DXSquad, specialising in XPO.  The blog is a superb resource for any XPO developers and really worth reading.  Michael is also a very active member on the DevExpress forums and may well come to your help with an XPO issue there.

XPO uses a classic INotifyPropertyChanged pattern and passes a string of the changed property name into SetPropertyValue method.  You can see this below:  

  1. public class Customer : XPObject
  2. {
  3.    private string _number;
  4.    public string Number
  5.    {
  6.       get { return _number; }
  7.       set { SetPropertyValue("Number", ref _number, value); }
  8.    }
  9. }

The problem with this approach is that the compiler can’t determine whether the string is correct or not, leaving you open to potential runtime errors.  Michael’s solution to this to generate a helper class that can be used in the property setter and he has a Visual Studio plugin that generates and refreshes the helper class for you based on your domain model. 

This is a great approach to the problem and you can read more about it on the homepage for Michael’s plugin, XPO_EasyFields.

Michael’s XPO_EasyFields plugin uses the free DXCore Visual Studio plugin from DevExpress.  Personally, I use Resharper and don’t have DXCore installed, so I thought I would share my approach to removing the magic strings - I use a helper class and lambdas to do this.  It looks like this:

  1. public class Customer : XPObject
  2. {
  3.    private string _number;
  4.    public string Number
  5.    {
  6.       get { return _number; }
  7.       set { SetPropertyValue(Property<Customer>.Name(x => x.Number), ref _number, value); }
  8.    }
  9. }

This relies on the use of a generic Property class and a helper method that gleans the property name from a Linq Expression.  The property class looks like this:

  1. public static class Property<T>
  2. {
  3.    public static string Name(Expression<Func<T, object>> expression)
  4.    {
  5.       if (expression == null) throw new ArgumentNullException("expression");
  6.       if (expression.Body is MemberExpression) return ((MemberExpression)expression.Body).Member.Name;
  7.  
  8.       if (expression.Body is UnaryExpression && ((UnaryExpression)expression.Body).Operand is MemberExpression)
  9.       {
  10.          return ((MemberExpression)((UnaryExpression)expression.Body).Operand).Member.Name;
  11.       }
  12.  
  13.       throw new ArgumentException(string.Format("Could not get property name from expression of type '{0}'",
  14.                                                 expression.GetType()));
  15.    }
  16. }

The magic comes from translating the little lambda expression x => x.Name to a string.  If I remember right, I originally based this on some code from Jeremy Miller, but there are various implementations out there.  Here’s and elegant one from Paul Stovell that’s focused purely on INotifyPropertyChanged. 

As Paul mentions in the above link, it’s worth noting that there is a performance hit when using this approach.  Michael’s approach of generating the code does not have any performance hit.  You may need to consider the performance issue if you have very high rates of properties being set. 

I did some simple performance tests that show a 10-15x overhead with my approach compared to Michael’s.  However, this only becomes relevant with a very large number of property sets.  For my usage scenarios the added quality benefit outweighs the performance hit, but you will need to carefully consider your scenario.

Lastly, to take this further, and get an even tighter syntax, I add this helper method to my persistent classes:

  1. protected void Set<T>(Expression<Func<Customer, object>> property, ref T holder, T value)
  2. {
  3.    SetPropertyValue(Property<Customer>.Name(property), ref holder, value);
  4. }

This allows the setter to be even more compact:

  1. private string _number;
  2. public string Number
  3. {
  4.    get { return _number; }
  5.    set { Set(x => x.Number, ref _number, value); }
  6. }

The downside is that you need the helper method in each class.  Down to taste that really, but I always go for the tighter syntax wherever possible! 

You can get the code from bitbucket and browse the salient parts here.

Thursday 21 January 2010

Sometimes It Just Works

Some things in life that just do what they say they will do and when this happens you get blown away. 

VMware Workstation says it lets you use Visual Studio to debug an application that is running on a virtual machine.  I used this recently and was blown away by how easy it was to set up and by how amazingly useful it was.

The story is that I released a new build for informal testing, but it could not be installed.  I installed it onto a clean XP VM (yeah, I should have done that already…) and got the error myself.  However, there was no error information coming back from the application as the failure was happening before the logging layer was instantiated.

I was stuck.  I could reproduce, but had no other information to help.  Then I remembered that VMware Workstation had the facility to debug apps running on VMs.  So, I followed the instructions (yes, I was desperate enough to read the VMware help file!!) and set up a VM for remote debugging.  This was pretty swift to achieve and I then started a debugging session on the VM from Visual Studio. 

Almost immediately I could see what was happening: it was my bad – I’d just forgotten to include a third-party assembly with the build.  My dev box was happily loading it from the GAC and so I couldn’t see I’d missed anything.

VMware Workstation just did what it said it would do.  in doing so, it got me out of a sticky situation.  Also, it says it has the ability to record and replay a debugging session…maybe next time, eh?

In the meantime, and whilst loving the things that go right, here’s a shot of the error from VS debugging on the VM:

image

Thursday 7 January 2010

Friendly OS Name from WMI

When you want to find out what operating system your application is running on, System.Environment.OSVersion is not very readable.  You can get a nice friendly name using WMI like this:

  1: private static string GetOSName()
  2: {
  3:    const string query = "SELECT * FROM Win32_OperatingSystem";
  4:    var searcher = new ManagementObjectSearcher(query);
  5:    var results = from x in searcher.Get().OfType<ManagementObject>()
  6:            select x.GetPropertyValue("Caption");
  7:    return results.Any() ? results.First().ToString() : "Unknown";
  8: }


This will give you something like "Microsoft® Windows Server® 2008 Enterprise ".