I remember why I hate InstallShield

I’m back to getting the Installer ready for our pending release. In fact I’m the critical path at the moment. Yet I’m having convulsions with how the Install process works.

For so long I’ve wanted to use WiX to build MSI installers, and thus have been spending vast time reading how to do the more trickier tasks (more than xcopy) and yet I find not all is perfect in MSI land either. Surprise!

As far as my product goes, WiX/MSI will solve my problems. I love the declarative nature, thus giving you powerful roll-back functionality, but from the correct management of prerequisite it seems woefully shortcoming.

Where-as my InstallShield install-script installer, feels dirty as it’s so procedural, and thus I have to hand roll all the un-install, minor/major upgrade paths by hand, but can do what I like when I please.

But the real issues with InstallShield is that is crashes my machine when I’m not even using it! via it’s stupid agent.exe program, that goes 100% CPU (dual core machine so not a complete killer) and makes explorer run like a dog. And this service they are trying to sell as a value add-on, yet it ruins my development machine, hmm no thanks.

Or maybe it’s the licensing. I have both IS 12 and the newer IS 2008, but have chosen to stick with 12 as 2008 has a Vista like phone home silliness. I want to have it installed on our build machine, so all production builds are done in a clean location, and can be run by anybody from the dev team, but once a year have it on my machine also, while I’m tweaking the project. Yet that’s not going to work with the newer version.

So I’m stuck between a rock and a hard place.

The Black Swan

Michaela bought me The Black Swan by Nassim Nicholas Taleb for Christmas.

The Black Swan - Cover
The Black Swan - Cover

It was a perspective changing book. I loved it.  Buy it, read it, now!  I’ll wait…..

Right, so now we are in the same head space, wasn’t it just great!  Just like it’s back cover says, The Impact of the Highly Improbable.

I loved the concept that it only takes 1 black swan to prove that All Swans are White is wrong, yet you can never prove it’s correct.  I loved how he expands this idea to show how most people’s concept of risk management is really sticking your head in the sand and hoping for the best.  As they do not manage the risks (the impacts) but use tiny probabilities to feel happy that it won’t happen (short term thinking and looking out for the quarterly/yearly bonus).

Another section that strike me quite personally, was how we cannot forward project.  One example he uses, is that when thinking about buying a new car you get excited about how grand it will be, yet you fail to remember feeling that way about your current car, and you fail to project the loss of that feeling going forward.  So tying that to me, as a software developer. When you get someone else’s code, and the first things you say is what were they thinking, where’s the documentation, it’s all spaghetti.

Yet I fail to see how my grand vision of perfect code, done correctly, will be compromised due to time constraints, or prioritised by business value add. Or how there will be bugs in other sub-systems, needing ugly work around code. I’ll be rushed off my feat, and thus not document it, ever, and when asked to, I’ll ask documents (which will ages quickly) or bug fix, and you know what will win. And that’s how it is, because of the scale of software we are developing, and how we are part of a bigger company, thus need to be profitable and resources are limited (as the really should be). So I give myself all the credit of plans, and saying it’s alright to shortcut here, I’ll fix it later, but all my predecessors were muppets, that had no vision, and wrote unreadable code!

So my current mental track is to try forgive others, as I hope to be forgiven myself.

I enjoyed this book enough, that as I was reading it, I was already looking forward to reading it again, as I couldn’t recall all the things that made me go - da, now you point it out!, but it sure happened a lot.  Michaela got tired of me excitedly recalling (poorly) the book to her!

Wikipedia’s The Black Swan page is quite a good summary.

Paradigms of Artificial Intelligence Programming - Finished!

I’ve finished reading Paradigms of Artificial Intelligence Programming: Case Study in Common Lisp. On the whole, the book was a slog (bought it 4 months ago), just like its name. A top quality slog, but reading large chunks of Lisp while not taking the time to enter each program and getting a feel for how it “works” was hard.

The historic perspective and evolutions of early AI programming was fantastic. I loved the section on natural grammar/parsing, and the impact of how you store your “ model data” impacting how you can process the input, made a lot of sense. Before reading that section, I had spent a few nights grappling with how I wanted to parse text, and how I’d store my knowledge and I was getting mentally caught up in the chicken - egg of it all, so it seemed very timely after that to read how it was really tricky (Chapter 14 - Knowledge Representation and Reasoning).

Now that I have read the book, and gotten an overall comprehension of what it covers, I look forward to using it as a reference for learn Lisp and for fundamentals of AI development.

One of my takes one the whole Lisp front, is that it is really nice the idea of not having to have every thing strongly typed up front. Seeing how solutions organically evolve is quite a strong argument for dynamic languages. I also really liked how functional composition stacks blocks of doing together to make a greater whole.

Practical MythTV

I’ve been reading Practical MythTV over the last few weeks, and it hasn’t helped my longing for PVR system.

Alan at work has a very nice front-end/back-end setup which I would love to duplicate, and this book certainly has been giving me idea’s about how to go about it.

My main goal is beyond classic DVR functionality (record and time-slip playback), is to be able to watch the odd MP4 style download also. Thus a $500 DVR is not the exact fit. I also want something silent in the living room, so it can run 24x7. Much like the Squeezebox but for video also.

So back to the book. Flipped through large parts, as I got the point, but still the details of how to configure the parts of the system seemed detailed enough that I’d borrow the book again to have with me as a guide. Not sure I’d buy the book however.

So really the book was to fuel the fire of desire, and it worked. Now I just need to budget it all up, and get the wife acceptance factor on my side of the debate.

House Update - Wall Studs replaced

Over the two weekends of the Christmas break, Harvey and I worked on the house.  Doing one side of the bay window each weekend

We replaced twice:

  • the double 4”x 2” corner stud
  • the 4”x2” middle stud
  • the 4”x3” window stud, which holds the lintel
    Wall studs replaced
    Wall studs replaced
  • replaced the 2”x 2” and 2”x 5” corner plates (not sure correct term)
  • replaced the weatherboards
    Wall cladding replaced
    Wall cladding replaced

Tasks left:

  • weatherboard the bay window
  • lay floor in the room
  • plus small tasks

We are estimating three more days, then we will be done! Oh my god, I’m getting so sick of the time sink of this project, but we’re on the back straight, and we’ve come so far.

WPF: Making a Expander look like a GroupBox

This may be long, but at the end of the post, you should be able to change the look of any WPF control.

I have a Win32/WFC application that I’m porting to .Net/WPF.  It is a simulator, so has lots of values to set/tweak.  The current application has lots of GroupBox clustering options together, yet most are only needed some of the time (like before starting), and some options should only be used if other options are not.

With this in mind, I wanted to be able to expand/collapse groups.

My first attempt was to add a button to the header of a GroupBox, and in the code behind alter the Visibility=”Collapsed”, but that felt clunky.

I then found the Expander control, which does exactly what I want, yet as a UI control I find it ugly.  I guess it is good for building Outlook tool panels.  This is where the power of WPF shines.  I can take the expander and give it a new skin and make it look like a group box, but keep the boarder visible while the content is collapsed.

GroupBox and Expander in default style
GroupBox and Expander in default style

The first place I looked was is MSDN, and tried the Expander ControlTemplate example, but the theme was completely different from the normal theme, and that was what I was wanting to capture.

So I then asked on the NZ .Net mailing list, and Ivan came up with some helpful options:

  • Use Expression Blend 2
  • Use the BAML Viewer Reflector add-in
  • or try MSDN under Controls > Control Customisation > ControlTemplate examples (the above example)

So I tried the idea’s in exciting order first, aka Reflector and the BAML Viewer. In short this was the wrong choice, here’s why, it took me ages to find that I needed to look at the correct DLL:

You will need to open one of the theme DLLs, e.g. PresentationFramework.Luna.dll or PresentationFramework.Aero.dll (use Open Cache since they are in the GAC) - Ivan

Once I had the correct Xaml, I realised that the internally referenced static resources were not named correctly, therefore you could not tell what was used where. That was a deal breaker.

So I then turned to what I thought would be the trickiest option installing and using Expression Blend 2.

First wrong assumption was, that it was now released and thus I’d need a license. It’s still in development, so is still free.  It was also small (compared to Visual Studio installers) at 25MB.

Once I got Blend installed, changing the look of controls is SO EASY:

  1. Add the control you want to copy the look of, to the design surface

  2. Right click on the control

  3. Click Edit Control Parts (Template)

  4. Click _Edit a Copy

    How to copy a WPF control’s controll template
    How to copy a WPF control’s controll template
  5. Save as something.xaml

  6. Add the control you want to change to the design surface

  7. Repeat steps 2 - 4

  8. Save as IntelligentName.xaml

  9. Merge the two templates to give you the desired look/feel/interaction

After having done this I ended up with a Expander that looked like a GroupBox

WPF Expander with the look of a GroupBox
WPF Expander with the look of a GroupBox

You just add

Style="{StaticResource GroupBoxExpander}"

to your Expander, and I also tend to set

IsExpanded="True"

The code for the GroupBoxExpander.Xaml is at end of this post. Remember to include the ResourceDictionary in your App.xaml via a Merged Resource Dictionaries

Some things I learnt on the way:

  • There are some quite clever uses of a Grid, to get the Board half way through the text of a GroupBox

  • I really like WPF’s separation of concerns

  • I quite like typing Xaml by hand

      <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
      <Style x:Key="GroupBoxExpanderToggleButtonStyle" TargetType="{x:Type ToggleButton}">
      <Setter Property="Template">
      <Setter.Value>
      <ControlTemplate TargetType="{x:Type ToggleButton}">
      <Grid SnapsToDevicePixels="False" Background="Transparent">
      <Ellipse HorizontalAlignment="Center" x:Name="circle" VerticalAlignment="Center" Width="15" Height="15" Fill="{DynamicResource ButtonNormalBackgroundFill}" Stroke="DarkGray"/>
      <Ellipse Visibility="Hidden" HorizontalAlignment="Center" x:Name="shadow" VerticalAlignment="Center" Width="13" Height="13" Fill="{DynamicResource ExpanderShadowFill}"/>
      <Path SnapsToDevicePixels="false" x:Name="arrow" VerticalAlignment="Center" HorizontalAlignment="Center" Stroke="#666" StrokeThickness="2" Data="M1,1 L4,4 7,1" />
      </Grid>
    
      <ControlTemplate.Triggers>
      <Trigger Property="IsChecked" Value="true">
      <Setter Property="Data" TargetName="arrow" Value="M 1,4 L 4,1 L 7,4"/>
      </Trigger>
      <Trigger Property="IsMouseOver" Value="true">
      <Setter Property="Stroke" TargetName="circle" Value="#666"/>
      <Setter Property="Stroke" TargetName="arrow" Value="#222"/>
      <Setter Property="Visibility" TargetName="shadow" Value="Visible"/>
      </Trigger>
      </ControlTemplate.Triggers>
      </ControlTemplate>
      </Setter.Value>
      </Setter>
      </Style>
    
      <SolidColorBrush x:Key="GroupBoxBorderBrush" Color="#D0D0BF"/>
      <SolidColorBrush x:Key="GroupBoxHeaderBrush" Color="#0046D5"/>
      <BorderGapMaskConverter x:Key="BorderGapMaskConverter"/>
    
      <Style x:Key="GroupBoxExpander" TargetType="Expander">
      <Setter Property="BorderBrush" Value="{StaticResource GroupBoxBorderBrush}" />
      <Setter Property="BorderThickness" Value="1" />
      <Setter Property="Template">
      <Setter.Value>
      <ControlTemplate TargetType="{x:Type Expander}">
      <Grid SnapsToDevicePixels="true">
      <Grid.ColumnDefinitions>
      <ColumnDefinition Width="6" />
      <ColumnDefinition Width="Auto" />
      <ColumnDefinition Width="*" />
      <ColumnDefinition Width="6" />
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
      <RowDefinition Height="6" />
      </Grid.RowDefinitions>
      <Border CornerRadius="4" Grid.Row="1" Grid.RowSpan="3" Grid.Column="0" Grid.ColumnSpan="4" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="Transparent" Background="{TemplateBinding Background}" />
      <Border x:Name="Header" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" Padding="3,0,3,0">
      <Grid SnapsToDevicePixels="False" Background="Transparent" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2">
      <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition />
      </Grid.ColumnDefinitions>
      <ToggleButton Grid.Column="0" MinHeight="0" MinWidth="0"
      Name="HeaderToggle" Style="{StaticResource GroupBoxExpanderToggleButtonStyle}"
      IsChecked="{Binding Path=IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" >
      </ToggleButton>
      <ContentPresenter ContentSource="Header" RecognizesAccessKey="true"
      TextElement.Foreground="{StaticResource GroupBoxHeaderBrush}"
      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="3,0,0,0" />
      </Grid>
      </Border>
    
      <ContentPresenter x:Name="ExpandSite" Visibility="Collapsed" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
    
      <Border Grid.Row="1" Grid.RowSpan="3" Grid.ColumnSpan="4" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="4">
      <Border.OpacityMask>
      <MultiBinding Converter="{StaticResource BorderGapMaskConverter}" ConverterParameter="7">
      <Binding Path="ActualWidth" ElementName="Header"/>
      <Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/>
      <Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/>
      </MultiBinding>
      </Border.OpacityMask>
      </Border>
    
      </Grid>
      <ControlTemplate.Triggers>
      <Trigger Property="IsExpanded" Value="true">
      <Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
      </Trigger>
      <Trigger Property="IsEnabled" Value="false">
      <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
      </Trigger>
    
      </ControlTemplate.Triggers>
      </ControlTemplate>
      </Setter.Value>
      </Setter>
      </Style>
      </ResourceDictionary>
    

House Update - Under Floor Complete

Well the under floor part of the great house DIY of ‘07 is done.

In the process we have:

  • moved 2,500 kg’s of dirt and rubble from under the house
  • laid 100m2 of polythene ground sheeting
  • used 180m of tape
  • got a lot of sore muscles from crawling around in 30cm’s of space for days on end

But the floor looks good

Polythene Ground Sheeting - All done picture 1
Polythene Ground Sheeting - All done picture 1
Polythene Ground Sheeting - All done picture 2
Polythene Ground Sheeting - All done picture 2

Now on with:

  • laying the floor back down
  • replacing some wall studs
  • putting weatherboards back on outside of house

and it will be done!

Live Spaces Oddness

I keep getting Google Alerts for one of the posts from my old blog at simeonpilgrim.spaces.live.com. The strange thing is that I have turned off access to these pages to the public, only trusted people may view them, yet, nobody is in my trusted list.

So why is Google still finding the page, and telling me about it? If it’s private?

So I then went on a rampage deleting the blog posts from my spaces.live.com, and when the last two were showing, I noticed one was a post I missed moving to this blog.  In fact I had missed both.  So there are two new posts back dated to October 2005.  I wonder how many other posts I missed….

It’s quite odd reading old posts, as much has changed since 2005, and in other fronts little has changed.

I hope you have all had a merry Christmas, and enjoy the New Year!

The Producers

We went to The Producers at The Court Theatre on Saturday night (as a Christmas present from my mother).  It was a fantastic play, lots of humor and well rounded but over the top plot. As always the stage was a fantastic Rubik’s Rings of folding parts.

The Producers - A new Mel Brooks Musical
The Producers - A new Mel Brooks Musical

The play is running till the 16th of February, so if you get the chance, I highly recommend it.