Thursday, March 15, 2007

WFPad - DIY workflow designer

So previously I'd thought writing our own designer for Windows Workflow might be too time consuming, but today I found this lovely little designer which could be the basis for our own designer. It doesn't have any support for adding code to a workflow but I consider that a plus point. I don't actually want our business analysts to even see a code editor. If we can import and export to Visual Studio whilst keeping any code behind intact this may be a marvellous solution. Keep watching...  

Tuesday, March 13, 2007

Loving Windows Workflow, hating Windows Workflow

I've been messing around with Windows Workflow lately and it's a bit of a love-hate relationship. Here's what I love, the fact I've got a workflow runtime that I can host in any application and, even better, it costs nothing. Hosting the runtime and persisting workflows to SQL Server is also reasonably straightforward, although I'm not sure my implementation is rock solid (I'm sure I'll find out if/when we go live). I love the fact I can develop workflows in Visual Studio and I can drop into C# whenever the activities provided don't quite do what I want. I love being able to write my own activities so I can parcel up commonly used functionality. I love being able to plug activities and properties together without writing any code. But then I'd like to think a business person might be able to design workflows and I can't see them picking up Visual Studio to do that. OK, I can host the Designer as well, but that's a pretty big job that I don't have time to do. I guess we could look at using SharePoint or BizTalk, but that would rather defeat the purpose of using Windows Workflow, which is primarily the cost. This seems to be the major problem workflow has always faced, making it simple enough for your average business person to understood (not suggesting they are simple of course...) but powerful enough so it can be used for real integration work. Coming from a background of using Metastorm e-Work there's a few obvious things missing from Windows Workflow that are available in e-Work. One is roles management, the other is easy forms integration. I guess both can be achieved but I need to investigate how easy it will be to do them, especially integrating forms in a fairly generic way. There is a good reason for not providing these features, since Windows Workflow is meant to be database and client platform agnostic. As ever, making a product as flexible as possible tends to make it somewhat complex and I think Windows Workflow has turned up the flexibility to 11. I have a few other niggles. Versioning doesn't seem to be supported. Workflows are persisted using .NET serialization so rebuilding a workflow assembly can cause any running workflows to fail. In fact I've had situations where I'm unable to do anything with a workflow, even terminate it. One other problem is there seems to be no simple way of getting data in and out of a workflow, without designing this data exchange into the workflow itself, something I was hoping to avoid since I was hoping to be able to do it in a generic way. But overall, given it's a version 1 product, I think Windows Workflow is pretty cool. Hopefully some of my problems are just caused by not understanding how it all fits together, so it's time for me to go and read a book.

Thursday, March 08, 2007

Panic Over - Climate Change is a Swindle

I was under the impression that we were all in agreement, that climate change is happening and it's out fault. But according to Channel 4's documentary this evening, we've all been conned. Apparently, although historical rises in CO2 do match rises in temperature, it's the rises in temperrature that drive the rises in CO2 rather than the other way round. I get the feeling that if this were the case, there would be a few more dissenting voices in the scientific community so I won't be going out to buy a mechanical hippo tomorrow. Even if it is true, the fact is fossil fuels will run out one day so we have to find alternatives, and the sooner we start to do that the better.

Sunday, March 04, 2007

Is Peak Oil here?

Apparently Saudi oil production was down 8% in 2006. I don't know enough about the subject to know if this is important or not, but it makes for interesting reading. http://www.theoildrum.com/node/2325

New template

I've finally taken the plunge and upgraded my template for the latest version of the Blogger software. I think the design looks much slicker and the template editing tools in Blogger look more powerful, although I haven't really done much with them yet. I've lost a few things from my template which I will be adding back when I notice them. Edit- Yes, the template editing is much better. Adding tags to posts is a pretty poor experience though. It looks much like adding tags in GMail but the usability is pretty poor. If you add a tag to a post, you're then sent back to the top of the first page of your posts after applying the tag. You can choose to show 300 posts per page but then it all gets very slow and after applying a tag to a post, the post remains selected. This means you have to trawl through all your posts again to find the post to deselect it before adding any other tags.

Wednesday, February 21, 2007

Sorting in a DataGrid

There doesn't seem to be a lot of information around on getting sorting in a WinForms DataGrid to work with custom collections. So I've done the hard work for you and here it is. First I wrote a sorting class, hopefully generic enough to sort pretty much any kind of simple data types (if your collection contains other objects you'll probably need to update this somewhat).

  internal class Comparer : IComparer
  {
    private PropertyDescriptor sortProperty;
    private ListSortDirection sortDirection;
    public Comparer(PropertyDescriptor sortProperty, ListSortDirection sortDirection)
    {
      this.sortProperty = sortProperty;
      this.sortDirection = sortDirection;
    }

    #region IComparer Members

    public int Compare(object x, object y)
    {      
      Type propType = sortProperty.PropertyType;
      int sort = 0;
      if (propType == typeof(string))
        sort = string.Compare((string)sortProperty.GetValue(x), (string)sortProperty.GetValue(y));
      else if (propType == typeof(DateTime))
        sort = DateTime.Compare((DateTime)sortProperty.GetValue(x), (DateTime)sortProperty.GetValue(y));
      else if (propType.IsEnum)
        sort = (int)sortProperty.GetValue(x) - (int)sortProperty.GetValue(y);
      else if (propType == typeof(int))
        sort = (int)sortProperty.GetValue(x) - (int)sortProperty.GetValue(y);
      else if (propType == typeof(Type))
        sort = string.Compare(sortProperty.GetValue(x).ToString(), sortProperty.GetValue(y).ToString());
      else if (propType == typeof(bool))
        sort = string.Compare(sortProperty.GetValue(x).ToString(), sortProperty.GetValue(y).ToString());
      else
        throw new NotSupportedException();

      if (sortDirection == ListSortDirection.Descending)
        sort = -sort;

      return sort;
    }

    #endregion
  }

Then I had to implement the IBindingList interface. Actually most of the IBindingList interface is redundant (makes me wonder why it wasn't broken down into a few smaller interfaces, ISortList, ISearchList etc), so here are the bits that are different to the stubs provided by Visual Studio.

    void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction)
    {
      sortProperty = property;
      sortDirection = direction;
      objectList.Sort(new Comparer(sortProperty, sortDirection));
    }

    private PropertyDescriptor sortProperty;
    PropertyDescriptor IBindingList.SortProperty
    {
      get
      {
        return sortProperty;
      }
    }

    bool IBindingList.SupportsSorting
    {
      get
      {
        return true;
      }
    }

    bool IBindingList.IsSorted
    {
      get
      {
        return (sortProperty != null);
      }
    }

    void IBindingList.RemoveSort()
    {
      sortProperty = null;
    }

    private ListSortDirection sortDirection;
    ListSortDirection IBindingList.SortDirection
    {
      get
      {
        return sortDirection;
      }
    }

objectList is my internal ArrayList that contains the collection of objects I'm interested in.

I'm not entirely happy with this solution. I have a lot of collection classes and each one has this same bit of code in it, which always smells a bit bad to me. At some point I might try to create a base class that encapsulates this functionality but it doesn't look too straightforward, since IBindingList requires IList, ICollection and IEnumerable implementations as well... 

Tuesday, February 20, 2007

Metastorm Resources

As well as getting hits from people searching for remedies to their medical problems with their bell ends (hint: go and see a doctor), I also get a few hits from people trying to track down information about Metastorm e-Work/BPM. So here's a short list of potentially useful sites.

Process Mapping - OK, it's my employer so I'm biased but it has some useful stuff. If you develop with e-Work be sure to grab a copy of the Procedure Documenter Designer add-in, which not only automatically documents your procedure but also checks for problems in your procedure that are missed by the Designer's validation.

Process Mapping Forums - OK, it's my employer again but if you're looking for an online community to discuss e-Work issues, this is definitely the best place to go. The official Metastorm newsgroups are like a ghost town, the once great eworkdev.org is now a site about Chinese babies and the only other one I'm aware of, eworkhelp.org, seems to be dying due to lack of people and increasing spam.

FreeFlow - Hmm, alright, this is mine... But if you want to integrate .NET and e-Work, these class libraries may well help. There's also a replacement for the abysmal Metastorm admin tools, which I use everyday (can't remember when I actually used the official tools) 

BRD - Thought I better add something that hasn't got anything to do with me just to make me look a little bit impartial. BRD produce the Swift client, an alternative web-based client, that provides quite a few features not available in the standard Metastorm client.

If you have any other links, let me know and I'll update this list. 

Thursday, February 15, 2007

DataGrid copy to clipboard

Here's some code I knocked together to copy the contents of a WinForms DataGrid to the clipboard. Probably won't work for all possible data sources but it was good enough for my needs. 

    public void CopyToClipboard()
    {
      StringBuilder builder = new StringBuilder();
      for (int i = 0; i < ts.GridColumnStyles.Count; i++)
      {
        if (i > 0)
          builder.Append("\t");
        builder.Append(ts.GridColumnStyles[i].HeaderText);
      }
      builder.Append(Environment.NewLine);

      CurrencyManager manager = (CurrencyManager)BindingContext[DataSource];

      if (DataSource is DataTable)
      {
        DataTable dt = (DataTable)DataSource;
        foreach(DataRowView r in manager.List)
        {
          for (int i = 0; i < dt.Columns.Count; i++)
          {
            if (i > 0)
              builder.Append("\t");
            builder.Append(r[i].ToString());
          }
          builder.Append(Environment.NewLine);
        }
      }
      else if (DataSource is IList)
      {
        for (int i = 0; i < manager.List.Count; i++)
        {
          object item = manager.List[i];
          Type objectType = item.GetType();
          for (int j = 0; j < ts.GridColumnStyles.Count; j++)
          {
            string colName = ts.GridColumnStyles[j].MappingName;
            PropertyInfo propInfo = objectType.GetProperty(colName);
            object propertyValue = propInfo.GetValue(item, null);
            if (j > 0)
              builder.Append("\t");
            builder.Append(propertyValue.ToString());
          }
          builder.Append(Environment.NewLine);
        }
      }
      else
        throw new NotSupportedException();

      Clipboard.SetDataObject(builder.ToString(), true);
    }

Saturday, February 10, 2007

Resizing columns to fit in a DataGrid

I wanted to automatically set the width of columns in a WinForms DataGrid to something sensible based on the contents (using .NET 1.1 for a number of reasons). I've seen the solution to this in a couple of places but they didn't work for me because I'm using a grid that inherits from DataGrid and adds a few helper methods. So here's what I've come up with.

    public void AutosizeColumns()
    {
      Type t = GetType();
      t = t.BaseType;
      MethodInfo m = t.GetMethod("ColAutoResize", BindingFlags.Instance  BindingFlags.NonPublic);

      for (int i = 0; (i < TableStyles[0].GridColumnStyles.Count); i++)
      {
        m.Invoke(this, new object[]{i});
      }
    }

Sunday, February 04, 2007

The CSS media attribute

I was going to write about this some time ago and never got round to it but Jeff Atwood covers it much better than I could ever hope to. Another reason I thought I'd highlight this is after a conversation with one of our clients who'd paid a company to write an ActiveX control to produce printer friendly versions of web pages. There really wasn't any need, it's trivially simple to produce a stylesheet for printer-friendly output, generally all you need to do is hide some of your headers and menus etc. Even with my pathetic CSS skills I managed to create one for the Random Pub Finder.

On the other hand I'm not so sure about the use of a handheld stylesheet though. I did one of these for the Random Pub Finder as well, but as far as I can see we never get any hits from handheld devices. Also, I may be wrong but I think quite a few handheld devices actually ignore the handheld stylesheet and just render websites using the standard stylesheet. This is probably due to the lack of websites that actually provide a handheld stylesheet, meaning any handheld device needs to be able to cope with full-size pages anyway. And finally, it's a right pain testing your site against the huge number of devices out there, particularly as the emulators always seem to be a pain to set up.

Friday, February 02, 2007

Installing a .NET assembly with COM interop

I've written a .NET 1.1 assembly that needs to register for COM interop. I've been using the Visual Studio 2003 installer to build my installer, because it's generally good enough for what I'm doing and it's free. OK, it's not exactly free, but who buys Visual Studio for the installer bits?

Anyway, the installer had been working fine by setting the Register property of the assembly to vsdrpCOM but when I went to test the installer I'd built today after some changes to the assembly it wasn't getting registered. Oddly the install completed and didn't suggest there was a problem but the registry was empty. I could register the assembly using regasm, but that doesn't seem like such a good solution for customers!

So after a not so quick Google later I came across this newsgroup posting (near the bottom) which showed a solution to the problem. And it worked. Problem solved. What I particularly like about this solution is that I'm now back in control of registering my assemblies, rather than being in the hands of the installer's black box implementation, which I've had weird problems with before.

Thursday, February 01, 2007

So what is a bell end?

I noticed that a search for what's a bell end on Google brings up this site at number one, so I thought I better answer the question.

So here goes, bell end refers to the end of a man's, er, manhood. The name came about because it's shaped somewhat like a bell (go on have a quick check, nobody's looking) and it is, in fact, the end. It's a simple as that, although it's often used as something of a derogatory term, where someone might say "he's such a bell end".   

The obvious follow on question is why on earth I chose it as my blog name? And the answer to that is I'm not entirely sure. I've certainly been called it quite a few times (due to the surname) and couldn't think of anything more appropriate at the time.

BlogSpot not very well

Lots of people getting a bX-vjhbsj error, as am I. So you probably can't see this...

Wednesday, January 24, 2007

Snow


This morning we woke to a world of white. As is usual with snow in London it didn't last very long. It had all melted by lunchtime. So here's the photographic evidence.

Tuesday, January 23, 2007

Skype has reached critical mass

Looking at my Skype client running today, I see there are nearly 9 million people logged on as I write this. Some would say that's enough to show Skype has reached critical mass. But for me the real sign that Skype will soon take over the world is this. My mum uses Skype. I don't mean it's installed on her computer and she ignores it. No, she actually called me up on it the other day. And today she started an instant messaging session with me. So congratulations to Skype for writing a piece of software that is simple enough for a pensioner with techno-fear to use. And congratulations on your impending world domination. 

Friday, January 19, 2007

Things annoying me today

Empty try-catch blocks - "Oh shit, this bit of code fails, I can't be bothered working out what's going on, I'll just catch the exception (and any other exceptions that are ever thrown) and ignore it. Oh and I won't bother putting a comment in the code to explain why I'm catching this particular exception, cos I don't really know why I am."

Well, I guess the thought process is something like that.

Pointless member variables - OK, so you know what a class is and you know what a member variable is, but that doesn't mean every single variable has to be a member variable. It doesn't make your code more object-oriented, it just makes it more complex. If it's only used in one function, then it probably only needs to be declared in that function. In a managed environment, it means the variable goes out of scope earlier and doesn't have to live for the entire life of the class instance. And your code is more maintainable. Although I'm guessing maintainability wasn't the prime concern of whoever wrote this app...

Wednesday, January 17, 2007

Why you should be using the .NET Framework

Larry Osterman has written a series of posts about software contracts. Well that's what they are meant to be about, but in the end they've been more about the fact that using the PlaySound API asynchronously is really amazingly difficult. One problem is that it's not documented particularly well, but the main problem is the design. The caller allocates some memory, which it must clean up after the sound has finished playing, but if you play it asynchronously you don't get any notification of when it has finished. There's a number of solutions, like kicking off the call synchronously in a separate thread or polling to see when the sound has finished. Larry even went so far as to provide some code to find out how long a WAV file is. Unfortunately some developers 'solve' the problem by just never freeing the memory.

Anyway, this just reminded me of what a complete PITA the Windows API can be, with weird structures and pointers to pointers, and all the docs expecting you to be a C programmer. To be fair, lots of it was designed 15 or more years ago, when PCs were completely different beasts to what they are now but I'm so glad most of my development is now using the .NET Framework. And playing a sound? Actually that was a gaping hole in .NET 1.1 but .NET 2 has the SoundPlayer class. For an async experience, call AsyncLoad, respond to the LoadCompleted event and then call Play and that's it.   

Friday, January 12, 2007

IE7 Uptake

According to the IE blog, they reckon 25% of web users are now using IE7. I'm seeing about 20% on my sites, but I bow to their bigger sampling space. Even so, it looks like I was somewhat over-optimistic with my prediction.

Thursday, January 11, 2007

Things annoying me today

FOR XML RAW - Why on earth would you ever use this in a stored procedure? OK, I can think of one use, when you want to do some kind of XSLT on the stored procedure output to produce some HTML or whatever, but not just so you can treat the output from a stored procedure as an XML document. What's the point? Just traverse the record set using the provided database classes.

Commented out code - If you're using a source control system (and if you're not then you're doomed), why leave commented out code lying around? It's all stored away in the file history. If I do a search for a call to a function, finding lots of commented out code is a waste of my time.

Copy and paste code - It's great to fix a bug in some code, then to find it's been reproduced verbatim in 4 other places in the project...

Monday, January 01, 2007

John Naughton's predictions for 2007

I always read John Naughton's column in the Observer, I'm not really sure why. Sometimes he has some valid points but he seems so consumed with hatred for Microsoft that he often completely loses the plot. His predictions for 2007 (towards the bottom of this article) seem to me to be some way off the mark.

First up, we'll see the "continued decline of Microsoft". He's been predicting this for so long, he's bound to get it right at some point. Apparently Vista may be the last version of Windows, er why? There's nothing in the article to back up this theory. Also some customers may have to upgrade their hardware to run it. Nothing new there, that has been the case for every new release of Windows but isn't reason enough for it to fail.

Not only that, "The trauma of producing Vista has shaken Microsoft to the core". Really? Sure, it took longer than expected but then so does every bit of major software. He then goes on to say Microsoft has become a middle-aged company, a point that I do agree with. Of course the bigger question is whether Microsoft can continue to use its huge cash reserves and near monopoly position to overcome that particular problem.

He goes on, "the PC is no longer the cornerstone of our information ecology. The network has become the computer". Hmm, unless I'm mistaken every time I connect to the internet I do it through some kind of computer, I can't mind-meld with Google just yet. And most of those computers still run Microsoft software (about 90% of the ones that hit my sites).

Then he moves on to Google's rise. He says its dominance is "underestimated by the usual market-research statistics, which put Google's market-share in the upper forties". I agree with this point, our logs suggest Google is driving about 70-80% of our search traffic. But as the Internet Outsider points out this is not necessarily a good thing. Google is going to find it hard to increase its market share much more, so where will revenue growth come from, since most of its income is based on search?

Finally he moves onto virtualisation technologies being a big thing in 2007. He correctly points out that server farms use up a hell of a lot of resources but I fail to see how virtualisation is going to help here. Having two virtual servers running on one physical server doesn't double the processing power, since each virtual server will essentially have half the processing power of the real server, in fact slightly less due to the overhead of the virtualisation software. Where virtualisation is useful is for running a piece of software on a different OS. So a Mac can run Windows software or vice-versa. I think this could be very useful to a company like Microsoft, since it can forget about backwards compatibility in its operating system, instead letting incompatible software run in its own virtual machine, which in turn may mean their next OS release will be a little easier to get out of the door.