Sunday, April 29, 2007

SonicWall VPN Client for Vista beta

One of the problems I've had with Vista is the fact the SonicWall VPN Client doesn't work with it and SonicWall haven't released a new version for Vista. Well they've finally got their arse in gear and released a beta version of the VPN client.

Send an email with “subscribe” as the subject of the email to if you’re interested in participating in the beta program.

It kind of works for me, although after a while Vista complains that two PCs are connected to the network with the same IP address. Then everything falls apart. Restarting the VPN client and my wireless connection fixes the problem.

Addendum (28th October) - The SonicWall VPN client for Vista is now out of beta and it is all working fine for me now.

Phew, it's not just me

First off, Canary Wharf is one weird place. I haven't been there for a while but it's almost like it has a dress code, everybody is wearing a suit, or shirt and trousers at the very least. So when I rolled out of the station in my old jeans with a few days facial hair growth I thought I'd be picked up by the police as a terrorist suspect. Fortunately I didn't bump into any police men. I was fairly sure Credit Suisse wouldn't let me in either but perhaps they'd been warned that a group of geeks was visiting.

I was attending a London .NET User Group meeting for a talk about Windows Workflow. The first part of this talk was reasonably interesting, although it was clear the presenter has been reading the same book as me, so a lot of it wasn't new to me. But things got interesting when one of the guys who's been developing a WF application at Credit Suisse talked about their experiences. The things that came up were pretty much the same issues that I've come up against.

First, the versioning story just isn't there yet. Storing serialized objects in the database means upgrading workflows can be somewhat tricky, since after an upgrade the deserialization is unlikely to work. Which is why I think using serialization is generally a bad design decision, unless the life of the serialized objects will be very short (copying to the clipboard, sending an object across the wire etc). So they've been forced to write some code to get pertinent information from the live workflow, destroy the instance and recreate it using the new workflow version and re-assign the state data.

The second problem is actually caused by the same issue. You might think since the workflow is stored in a SQL Server database, you could just query it to find all the instances that have a particular property, but again the fact that the worklfows are opaque blobs means this isn't possible. They worked around this by extending the persistence service to store relevant data relationally whenever a workflow is persisted.

It's nice to know that most problems can be worked around. There is so much flexibility in the WF hosting and runtime that almost all of the default implementations can be re-implemented to do what you want. I just hope this doesn't lead to Microsoft not fixing what are clearly problems with the default implementations.

One final thing that was mentioned that I was coming round to thinking myself is that state machine workflows are actually the way to go for many kinds of problems. Most of the talk in books and the web seems to be about sequential workflows but I think state machines are actually a better way to go most of the time. Of course this may just be due to my background in Metastorm e-Work which uses something closer to a state machine than a sequential workflow.  

Friday, April 27, 2007

More Vista pain

I finally cracked. I'd had enough of the complete lack of support from Dell about my lack of sound on Vista. The guy said he'd get back to me, of course he never did. Emails to Dell got no response. Yeh I could kick off another support call but it would just involve several hours of them uninstalling and installing drivers and failing to get anywhere, which I've been doing pretty well myself for several months. To top it all off, Dell sent me an email asking me to fill in a questionaire about my customer service experience. When I clicked on the link, all I got was a message telling me my access had expired. They even sent me a reminder to fill in the survey a few days later, again access expired. Hey Dell, there may be a reason you're not getting much feedback on your customer service...

So I thought, stuff this I'll buy a new soundcard, £20 and all my pain will go away. It all started out really well, Vista recognised it, went away to find the drivers and everything installed correctly, or so it said. Then I tried to actually get some sound out of the PC, nothing, nada, zilch. I pressed the dreaded 'Test' button, 'Failed to play test tone'. Aaaagh! Cheers Vista, why couldn't you play the test tone? I almost long for the usual massive hex number, at least something to work from. The event log is empty.

So now I have no idea what the problem is caused by. Presumably it isn't a driver or hardware problem, so is my Vista install broken? I really don't want to reinstall the whole thing.

On another note, Vista has developed a nice habit of locking up completely, the mouse stops moving, the keyboard doesn't respond, CTRL-ALT-DEL does nothing, the only thing I can do is hit the reset button.

Five years, thousands of developers and what do we have? A prettier version of XP that for me is less stable and other than IIS 7 doesn't really offer much new.

Tuesday, April 24, 2007

Recruiters - how about reading my CV?

I'm not looking for a job currently but my CV must be out there somewhere on the internet from the last time I was looking for work. And it's pretty clear quite a few recruiters just do a keyword search and send out emails without actually ever reading my CV. So I've had emails about C++ positions, which I haven't touched for almost 10 years, PHP jobs, which I'm familar with but wouldn't consider a strong point, testing jobs and even jobs in the US.

Maybe the 'throw enough shit at the wall and some of it will stick' technique works but I suspect it's not highly effective. I tend to remember the recruiters who actually bother to ring me up and actually listen to what I have to say and if I ever need to contact a recruiter again I'll go to them first, since they appear to care about placing people in the right job. The others are simply helping to confirm the bad reputation that recruiters have.

Monday, April 23, 2007

The ZX Spectrum is 25 years old

And how old does that make me feel?* Get an emulator and download some great games at World of Spectrum, read more about the mad genius Clive Sinclair at Wikipedia.

* Short answer - very

Friday, April 20, 2007

How to solve virtually any technical problem

People ask me technical questions all the time. I have no idea why, I don't know any more than anyone, perhaps the fact I can find the answer to these problems leads people to think I actually know the answer. So I'm going to present to you the two steps to find the solution to almost any technical problem.

Google for it - The internet holds the answer to pretty much any question you can ask. The key to finding the answer is to know how to search. This is pretty much trial and error, if one search doesn't bring up the answer, try another phrase until you get something that looks related. If you're getting a specific error message, search for that.

Another point to make here is that if you can't find what you're looking for, consider whether what you're trying to do is a good thing to be doing. I remember trying to find information about hosting .NET WinForms controls in Internet Explorer and not having much luck at all. This was a big red warning light to me that perhaps even attempting to do this kind of work was a bad idea since it would appear very few other people were doing it.

Infinite monkeys - You know the saying, given an infinite number of monkeys with an infinite number of typewriters and infinite time, one of them will produce the works of Shakespeare. So it is with fixing technical problems. Try enough things and one of them will be the right answer. The key to this technique is only to make one change at once, otherwise one of your changes may fix the problem and your other change might break it again. Or you forget one of the changes you made and don't set it back to what it was before and you're in an even worse position.

So now I've given you the tools, you don't need to bother me anymore, OK? 

Tuesday, April 17, 2007

Buy less crap

The idea touted by Red that somehow we can help charities by buying more stuff is frankly preposterous. The idea put forward by Buy (Less) Crap is to not purchase more consumer tat and donate the money we would have spent to charity instead. Now that seems much more sensible. How many fecking iPods do we need anyway?

Monday, April 16, 2007

Doogal's guide to parenting

You can read every book by Gina Ford you want but from my vast experience (ahem) there are only two things you need to master when bringing up a child.

Bribery and blackmail. 

Friday, April 13, 2007

No really, total rewrites don't make sense

I just found this fairly old blog post about rewriting Delphi apps in C# which sits so well with how I think (and puts the point across far more eloquently than I could ever do) that I had to post the link.

The bottom line is if you have an old code base to maintain, rewriting it completely may seem like an attractive option, but there are other ways of getting to the same place without throwing away years of investment in that old code base.

Wednesday, April 11, 2007

Swimming to New York

I'm not the first person to point out the humorous suggestion from Google Maps when you ask for directions from the UK to the US (see step 36), but it got me thinking.

One of the shortcomings of Google Maps is that it has no knowledge of anything but driving so it won't advise me to jump on a plane if I want to get to the US. For that matter if I ask it how to get to London Waterloo from my house, it doesn't know anything about trains so again will tell me how to drive there. It doesn't know anything about congestion charging or parking charges either so doesn't realise only the super rich or super stupid would ever consider driving into central London.

Transport for London has the opposite problem because it completely ignores the driving option, which in some circumstances might make sense (try taking public transport from SW London to SE London without dying of old age on the way for instance).

A while ago I wanted to investigate transport options for getting to my dad's house in Spain. Here things get even more complicated. There are loads of different websites with information about planes, trains and ferries but I had to find them and then compare prices, times etc.

But none of this stuff is properly integrated. The data is mostly available so it just requires an uber geek to figure how to build a mashup site that takes data from all these different sites and pulls it together in one place. I need to be able to enter a start location, an end location and then be able to get results sorted on which is cheapest or fastest or most environmentally friendly and lets me buy all the required tickets. Presumably if somebody did make such a thing, they could probably finance it by getting commission on the bookings.

And another thought, my guess is one of the reasons people who may be concerned about the environment still take flights rather than taking the overland option is that it is so much easier to book a flight than to book the alternative train and ferry. Oh, and cheaper... Er, and quicker... But at least this site could remove one obstacle.

So, any takers?

Tuesday, April 10, 2007

Maintainable XSLT

Doing a search on Google for 'maintainable XSLT' doesn't throw up a great deal but it seems like something that is really needed. There seem to be lots of resources out there telling me how to code in XSLT, but I haven't found any telling me how to do it elegantly or testably (is that even a word?). I've been working on and off on a project that takes an XML file and spits out a HTML representation of it. When I started off I decided to go with XSLT, rather than generating the output in C# using an XmlWriter. I still think that was the right decision. Even though XSLT is pretty verbose, generating HTML any other way isn't too concise or pretty either.

It's not a big XSLT file by any means (about 1500 lines), but I'm already finding it hard to manage and the tool support just isn't there. Visual Studio 2005 is a step up from 2003, but there are still plenty of things missing. There doesn't seem to be a way to get an overview of an XSLT file by showing what templates are in it. This means some of the possible advantages of splitting it out into separate templates are lost. But even if I was to split it out into separate templates, the markup required to call a template means the XSLT file might actually get bigger due to the calls to the templates!

Another thing I'd like to see is the ability to go to the definition of a template from a call-template call, but that doesn't seem to be available. How about regions, like in C#? OK, I want all the features of the C# editor in XSLT, am I barking up the wrong tree? XSLT is fairly different to C# and I'm coming at this with the mindset of a C# programmer but are there different ways of handling this complexity? Where should I be looking for this information?

Wednesday, April 04, 2007

Method calls on value types and boxing

It was DevWeek 2005 and I was in a session with Jeff Richter about low level .NET things and I foolishly asked him a question. He looked at me as if I had asked the most dumb question ever asked by anyone, so I decided not to follow up on my question, even though I didn't feel he'd really given me the answer I was looking for.

So what was the question? Well he was describing boxing of value types and how it can cause performance problems so it was best to avoid it where possible, even though it's not always clear when boxing is occurring. I'd asked didn't boxing need to occur for any method call on a value type. On reflection I'm not sure this was a particularly dumb question but I've never really got fully to the bottom of it, mainly because it's never really been much of an issue to me. But here's my take on it, which may or may not be accurate. Boxing is only going to happen if the method call is a virtual method where the value type doesn't override the base object implementation. Now it might be boxing would also be required if the value type did override the base method (assuming boxing is required to get the virtual method table), if value types could be inherited from. But they can't so the discussion is kind of irrelevant. This may well be why value types can't be inherited from, but this is all frankly getting way too complicated for me to understand, so I'll quickly move on.

Anyway to illustrate the point, here's a little test C# application.

namespace ConsoleApplication2
  struct ValTypeTest
    int val;

    public ValTypeTest(int val)

    public override string ToString()
      return val.ToString();

  class Class1
    static void Main(string[] args)
      ValTypeTest thing = new ValTypeTest(34);

      int number = 34;


If you look at the IL code for this in Reflector using .NET 1.1 (I'll explain why I'm using .NET 1.1 shortly), you'll see this -

.method private hidebysig static void Main(string[] args) cil managed
    .custom instance void [mscorlib]System.STAThreadAttribute::.ctor()
    .maxstack 2
    .locals init (
        [0] valuetype ConsoleApplication2.ValTypeTest thing,
        [1] int32 number)
    L_0000: ldloca.s thing
    L_0002: ldc.i4.s 0x22
    L_0004: call instance void ConsoleApplication2.ValTypeTest::.ctor(int32)
    L_0009: ldloca.s thing
    L_000b: call instance string ConsoleApplication2.ValTypeTest::ToString()
    L_0010: call void [mscorlib]System.Console::WriteLine(string)
    L_0015: ldloc.0 
    L_0016: box ConsoleApplication2.ValTypeTest
    L_001b: callvirt instance int32 [mscorlib]System.ValueType::GetHashCode()
    L_0020: call void [mscorlib]System.Console::WriteLine(int32)
    L_0025: ldc.i4.s 0x22
    L_0027: stloc.1 
    L_0028: ldloca.s number
    L_002a: call instance string [mscorlib]System.Int32::ToString()
    L_002f: call void [mscorlib]System.Console::WriteLine(string)
    L_0034: ldloca.s number
    L_0036: call instance int32 [mscorlib]System.Int32::GetHashCode()
    L_003b: call void [mscorlib]System.Console::WriteLine(int32)
    L_0040: call string [mscorlib]System.Console::ReadLine()
    L_0045: pop 
    L_0046: ret 

As you can see, the call to GetHashCode causes the value type to be boxed, whereas the call to ToString doesn't, because ToString has been overridden whereas GetHashCode hasn't been. But if we look at the IL code in .NET 2, it looks like this

.method private hidebysig static void Main(string[] args) cil managed
    .custom instance void [mscorlib]System.STAThreadAttribute::.ctor()
    .maxstack 2
    .locals init (
        [0] valuetype ConsoleApplication2.ValTypeTest thing,
        [1] int32 number)
    L_0000: nop 
    L_0001: ldloca.s thing
    L_0003: ldc.i4.s 0x22
    L_0005: call instance void ConsoleApplication2.ValTypeTest::.ctor(int32)
    L_000a: nop 
    L_000b: ldloca.s thing
    L_000d: constrained ConsoleApplication2.ValTypeTest
    L_0013: callvirt instance string [mscorlib]System.Object::ToString()
    L_0018: call void [mscorlib]System.Console::WriteLine(string)
    L_001d: nop 
    L_001e: ldloca.s thing
    L_0020: constrained ConsoleApplication2.ValTypeTest
    L_0026: callvirt instance int32 [mscorlib]System.Object::GetHashCode()
    L_002b: call void [mscorlib]System.Console::WriteLine(int32)
    L_0030: nop 
    L_0031: ldc.i4.s 0x22
    L_0033: stloc.1 
    L_0034: ldloca.s number
    L_0036: call instance string [mscorlib]System.Int32::ToString()
    L_003b: call void [mscorlib]System.Console::WriteLine(string)
    L_0040: nop 
    L_0041: ldloca.s number
    L_0043: call instance int32 [mscorlib]System.Int32::GetHashCode()
    L_0048: call void [mscorlib]System.Console::WriteLine(int32)
    L_004d: nop 
    L_004e: call string [mscorlib]System.Console::ReadLine()
    L_0053: pop 
    L_0054: ret 

Now it's no longer clear whether boxing occurs or not, because both calls use the IL constrained opcode. It would appear this opcode has been added for a variety of reasons, but one of them is to help with binary compatibility, so if a value type changes so it adds an override for a virtual method or removes an override, it will still work without any changes to the calling app. The downside of this is that boxing is even more hard to spot than it was before.

Saying that, worrying about boxing is often not really worth the trouble. It smells of premature optimization and in most cases isn't likely to cause problems. Saying that, it does suggest if you're writing your own value types, you're probably going to want to override most of object's base methods, particularly GetHashCode, which is used in quite a lot of places.

Tuesday, April 03, 2007

The number one internet resource for Metastorm crap

It's always interesting to look through the search terms that have led people here or to the other sites I have something to do with. It's certainly a great work avoidance tactic. So I was pleased to see that the term Metastorm crap had landed somebody here. Then when I did a search for Metastorm crap myself I was even more pleased to see I'm number one for that search term. So there you are, come here for all the Metastorm crap you could ever need...

In fact I've just done a search for Metastorm shit and I'm number one for that as well! I must point out at this point that although the words may have appeared on the same page, they didn't actually appear in the same context... OK, they do now, but I'm not implying anything, OK?