Showing posts with label computers. Show all posts
Showing posts with label computers. Show all posts

Tuesday, March 07, 2017

Writing plugins for Octopus

Following on from my previous post about writing plug-ins, here’s the next installment of what may or may not become an irregular feature.

I’ve been using Octopus Deploy at work for several years now, and it is a great tool for automating the deployment of software; in my case, it turned a 20-page manual checklist that took 40 minutes to work through into a five minute fire-and-forget exercise. However, there are still little steps here and there that can’t be automated out-of-the-box, and that’s where we pick up our story.

We track our work-in-progress using JIRA, and one of those tedious post-release tasks is to update all the tickets, setting their status to Released and so on. So, given that JIRA exposes an API, and Octopus supports custom steps or step templates written in Powershell, why not combine the two and cross another manual step off the list?!

Show me the code!

Actually, I’m not going to post any code snippets this time – rather, I’ve published the source code to GitHub (something else I’m learning, after 15 years of Subversion), so go ahead and fork it. There’s not a whole lot of error handling in there at the moment, but it seems to do the trick. There are two files:

  • the original Powershell file, which you can open up and run in the Powershell IDE;
  • the Octopus Deploy step template, which wraps up the Powershell in a bit and parameterises it to make the code more reusable

Tuesday, February 14, 2017

Writing plugins for Exceptionless

Exceptionless is one of those tools that no developer should be without; it integrates with your application (currently .NET and NodeJS platforms are supported, with the promise of more to come), captures your unhandled exceptions, and provides you all sorts of tools to manage these exceptions.

The project itself is open source, and you can set up your own on-premise server to run the service, or you can use their cloud service if you don’t want the hassle of maintaining YADS (Yet Another D**n Server).
Their support is also very good; I’ve been working on a number of different scenarios (e.g. creating custom reports using the API to query for data, at least until they implement custom dashboards). The scenario that prompted this post was simple – when we deploy a new version of our API, we run a suite of automated regression tests to make sure we haven’t broken anything for our customers, but these regression tests include a large number of expected failure tests, which result in a large number of false positives being reported. So time to break open the coding tools and fix that…

Show me the code

The Exceptionless client provides a number of extension points, and after talking to Blake Niemyjski, who seems to be the main point of contact for enquiries, I whipped up the following plugin:
[Priority(5)]
public class SquelchExpectedExceptionsPlugin : IEventPlugin
{
    public void Run(EventPluginContext context)
    {
        var exception = context.ContextData.GetException();
        var httpContext = context.ContextData.GetHttpContext();

        if (ApiExceptionClassifier.IsAnExpectedException(exception, httpContext.Request.Headers))
        {
            context.Cancel = true;
        }
    }
}

internal static class ExceptionlessExtensions
{
    internal static HttpActionContext GetHttpContext(this IDictionary<string, object> data)
    {
        if (!data.ContainsKey("HttpActionContext")) return null;
        return data["HttpActionContext"] as HttpActionContext;
    }

    internal static Exception GetException(this IDictionary<string, object> data)
    {
        if (!data.ContainsKey("@@_Exception")) return null;
        return data["@@Exception"] as Exception;
    }

I had to add the extension methods as these are currently internal to the Exceptionless.Net library, while the ApiExceptionClassifier is a bit of business logic which checks for a specific header the the request to determine what sort of HTTP status code a given exception should result in (e.g. we want all ValidationExceptions to result in a 400 Bad Request). The plugin priority needs to be set to a low value so that it gets executed as early as possible – there’s not much point in gathering all sorts of data if we’re just going to throw it all away when the Cancel method gets called.
Once that was done, all that is left is to register the plugin in the API’s startup routine:
ExceptionlessClient.Default.Configuration.AddPlugin<SquelchExpectedExceptionsPlugin>();
And now, my regression tests don’t fill the Exceptionless reports with noise, unless an actual exception occurs during the process.

Friday, August 17, 2012

NDoc3 - a modern-day Lazarus

Back in the early days, the nDoc utility was the go-to solution for auto-generating API documentation for .NET applications. The build engine would parse the XML comments that the developer decorated class members with, and nDoc would take those results and produce MSDN-style web pages based on it. As an open source product, it attracted quite a following.
However, with the release of .NET Framework v2, nDoc failed to make the jump and instead imploded, being at the time quite a high-profile example of the risks of running an open source project:
  • the community might love your product, but if they don’t contribute something back (whether code, time or money) then it may not be possible for you to continue to develop it;
  • the vendor whose environment you are working in (in this case, Microsoft, but it could easily be another company. Apple, anyone?) can move into your space and deliver something that is good enough to draw mindshare away from your target audience. Actually, Sandcastle has never really been as good as, nor as easy to use as, nDoc, but the damage was done;
Fast-forward to the near-present time, and while Sandcastle continues to be unwieldy, the open source community is once again picking up the nDoc baton, this time in the form of nDoc3. In its current state, nDoc3 brings to the table support for .NET 3.5, but if you’re prepared to download the source code and build it yourself, you can get .NET 4 support as well. Of course, Microsoft moved the goalposts slightly this week with the release of .NET 4.5, so the cycle continues!
If you do want to try getting .NET 4 support, these are the steps that I had to go through (and a few hoops that I needed to jump through):
  1. Download the source code from Sourceforge, and extract the tarball to the file system;
  2. Rather than opening in VS2008 as the README file directs, I fired up VS2010;
  3. Building threw up a whole host of warnings, so I decided to try the provided NAnt build scripts;
  4. Building threw up a whole host of warnings, mostly about missing NAnt targets; in the end, I had to hack the NAnt.build file to pieces, first commenting out the references to the JavaDoc, Latex and LinearHtml documenters which, though references in the build file, don’t exist in the source code; I also had to comment out all the code related to testing, as again it referred to folders and/or files that don’t exist;
  5. I also needed to remove a duplicate AssemblyVersion attribute from Core\AssemblyInfo.cs;
  6. This at least allowed me to compile and run the application; however, when I tried to get it to document one of my own pieces of code, it quickly threw an exception which I traced back to an already-reported issue; fortunately, the user who raised the issue also submitted a patch, which while it has not been applied to the source tree, at least fixes the problem.
So now I have nDoc3 happily spitting out documentation for me; perhaps if time allows, I will look into writing a Wiki-format documenter.

Thursday, August 02, 2012

That didn't take long

I've been a devotee of the Sparrow mail app for Mac since it first came out. Its clean interface and seamless integration with GMail put it head-and-shoulders above Apple's own Mail application.

Unfortunately, those days are numbered - Google's recent acquisition of Sparrow is a near-guarantee that the application will receive no further work, beyond promised bug fixes. The timing couldn't be worse - with Apple having just released OS X Mountain Lion, there are bound to be problems with third-party applications, and it seems that Sparrow is already showing some.

I've been finding the UI locks up on me when composing or sending emails; labelling emails I want to keep isn't happening, nor is the deleting of emails that I don't. I can receive emails OK, so it's not a problem with my network or account. Quitting the application tends to cause it to hang, until I kill its process with extreme prejudice. And it's not just me who's seeing this:



All in all, the sort of experience that third-party developers would be rushing to fix; but with Google now calling the shots, how quickly will this happen? I'm not holding my breath.

Meanwhile, in the interest of actually Getting Things Done, I'm making do with Mail again.

Friday, January 27, 2012

A nice little trick with FluentAssertions

I love using FluentAssertions when writing tests for my code, it just makes the code so expressive in plain language. Recently I’ve been working on tests which involve the testing of lots of properties on a test result, and was looking for a way to remove a lot of the repetition involved.

Usually when asserting the properties on a test result, you can do it in three different ways. If I have my test class defined as below:

[TestFixture]
public class MyTestFixture
{
    private MyClass _subject; 
    private MyOtherClass _result;
 
    [SetUp]
    public void ExecuteTest() 
    { 
        _subject = new MyClass(); 
        _subject.Initialise(/*.. Some parameters here ..*/); 
        _result = _subject.SomeOperation();
    }
}

Then I can test the results as follows:

A. Assert all the properties in a test method

    [Test]
    public void ThePropertiesAreSet()
    {
        _result.First.Should().Be("Paula Bean");
        _result.Second.Should().Be("Brillant!");
    }

This is probably the usual way people do this. However, if the first test fails, the second test will never run, and we'll never know if our test method set the second result correctly or not, so we are lacking information as to the overall state of the test. Secondly, as the number of properties to test increases, you end up with a lot of visual noise, although Intellisense will at least take some of the effort out of creating the noise.

B. Assert the properties in a test method per property

    [Test]
    public void TheFirstPropertyIsSet()
    {
        _result.First.Should().Be("Paula Bean");
    }
 
    [Test]
    public void TheSecondPropertyIsSet()
    {
        _result.Second.Should().Be("Brillant!");
    }

With this approach, we now know if the setting of _result.Second was successful, even if _result.First failed. This extra information does come at the expense of more visual noise (the addition of another test method). Also, it allows you to really game the system if you get rewarded for the number of tests in your project :-)

C. Implement IEquatable

As the number of properties on MyOtherClass go up, you'll find a lot of code appearing in the test method. You can remove this by implemeting IEquatable<MyOtherClass> on MyOtherClass:

public class MyOtherClass : IEquatable<MyOtherClass>
{
    public override bool Equals(MyOtherClass other)
    {
        return this.First == other.First && this.Second == other.Second;
    }
}

(please note you should also really implement Object.Equals and Object.GetHashCode if you're going to use IEquatable, and for brevity, I've missed out a lot of the basic implementation of IEquatable<T>)

The result of this is that our test method now becomes:

    [Test]
    public void TheFirstPropertyIsSet()
    {
        MyOtherClass expected = new MyOtherClass { First = "Paula Bean", Second = "Brillant!" };
        _result.Should().Be(expected);
    }

Much cleaner and very expressive, and you'll probably find your code benefits elsewhere from having implementations of IEquatable<T>; but you do have to write that implementation (and perhaps unit test it too!). Yet more code...

This finally leads me to my point:

D. Use anonymous classes and FluentAssertion's AllProperties

How's this for simplicity?

    [Test]
    public void TheFirstPropertyIsSet()
    {
        _result.ShouldHave().AllProperties().EqualTo(new { First = "Paula Bean", Second = "Brillant!" });
    }

ShouldHave().AllProperties() does all the hard work of checking the properties. You can also use SharedProperties() if you only need to test a subset of the properties, and add IncludeNestedObjects if you have a more complex object model.

P.S. I love the story of the Brillant Paula Bean. It confirms all your prejudices about contractors.

Friday, January 06, 2012

New Year, New Resolutions

よいお年をお迎えください。

In other words, happy new year!

As far as making and keeping new resolutions go, I’d already failed miserably by January 2nd, probably setting a new low. The resolution was to take a photograph everyday and upload it to Flickr/Facebook, but that just didn’t happen. In fact, I haven’t picked up my camera for a week or two, and only used the camera in my phone to play around with Photosynth, which looks completely out of place on an iPhone, having been built for a Windows-based phone with no effort made to translate the UI design, but nevertheless, works very well.

However, the new year does afford me the chance to indulge in some spring cleaning, even if we are in the early throes of summer here in the Lucky Country. In particular, now that I am back at work, it means opening up the computer case, and having some fun with a rather large air compressor to remove all the dust that has accumulated since the PC was assembled. It also means that I can finally give it a good formatting and install everything afresh, something which every PC user should do at least annually.

Clean ALL the things!This of course reminds me just how many applications I have downloaded and installed in the past year. Just installing Windows 7 with all the layers upon layers of patches takes about half a day, and our internet connection at work feels much slower than my home internet connection.

To give you an idea of just how much stuff your typical Windows developer needs to make it through the day, here’s an approximate list. So far it’s taken me a whole day to download and install this lot, and I’m still finding those useful little apps that you forget aren’t included out-of-the-box.

System

  • 7-Zip – beats WinZip for compression any day;
  • DropBox – file synchronisation across almost any device;
  • Google Chrome – the choice of most developers;
  • Mozilla Firefox – the chose of most other developers;
  • Skype – for keeping in touch with our other offices around the world;
  • Virtual CloneDrive – for mounting all those application installation ISOs;
  • Windows Live Essentials – Mail, Messenger, and of course, Writer (which no self-respecting blogger should be without – definitely one of the most useful products to come out of Redmond);

Business Applications

Developer Tools

  • Beyond Compare – the best diff tool that I’ve tried (WinMerge is free and also very good, but I just prefer BC);
  • CruiseControl.NET – nothing inspires confidence in your day’s work like a row of green lights confirming that it compiles, the tests ran successfully, and the installation package is ready to be shipped;
  • Fiddler – if you have to send data across the network, you need this tool;
  • Notepad++ – syntax highlighting for almost every language out there, and tabbed windows too;
  • Smtp4Dev - for testing the sending of emails;
  • SQL Server Compact – for when the application you are developing will not need a full-blown database server;
  • SQL Server Express – for when application you are developing will need a full-blown database server;
  • Subversion (command-line, GUI, and IDE integration) – who wants to be a tightrope walker without a safety net?
  • Visual Studio – where I spend 95% of my time:
  • Windows 7 SDK – essential developer tools;
  • Silverlight – for rich web client development;
  • Silverlight Toolkit – the bits that Microsoft forgot in Silverlight
  • Expression Blend SDK – another set of bits that Microsoft forgot in Silverlight

Friday, March 25, 2011

A craftsman knows his tools

Those who have worked with me for any length of time will know that I’m always looking for ways to improve my ability as a programmer. It may be in researching the latest available tool libraries (my current new favourite is StoryQ, which is great for developing BDD-style tests, and NSubstitute, which is as easy to use as Moq, but without those annoying calls to .Object), or how to write better, more reliable, build scripts. Either way, learning new skills and refining existing skills is an essential part of any craft (I’m deliberately steering clear of the ongoing “software development isn’t a craft”/“oh yes it is argument – this still applies to trades and scientific disciplines).

This week I have been focusing on knowing my tools, and being a developer who works with Microsoft technologies, those tools inevitably centre around Visual Studio. One way to increase your productivity is to reduce the time you spend doing pointless activities, or rather, when faced with two ways of achieving something, to choose the quicker way. The most obvious form for a programmer is to learn to let go of the mouse; a little strange maybe, especially in an operating system that defines itself around the use of the mouse, but it really does act as a great big brake on your productivity. When I first started playing guitar, it would take me several seconds to visualise the necessary finger patterns in my head, and then position my fingers on the fret board. Now after much practising, I can see an F# minor chord written down and play it without having to even think about it.

The first step was to get rid of all the toolbars and icons. If there are no icons on screen, there’s not much point using the mouse to click them! The commands are still all there, and they can be accessed via the menu bar if I get really stuck. As a bonus, suddenly I have much more viewable area to concentrate on what really matters – the code.

So my first shortcut to learn was how to stop a debug session. I knew F5 to launch the debugger, but I always clicked on the Stop icon to stop it; well, it turns out that Shift-F5 was my new best friend. So far, so easy, and not too much time saved.

The next useful one was the Surround-with snippet; this is part of the excellent Resharper which really takes the heavy lifting out of Windows programming). I was working with code which was throwing exceptions, and there was no exception handler. Before, I would have used the mouse to click just above the offending line of code, then typed in the standard try/catch blocks, then selected the offending line of code and cut’n’paste it into the try {} block, then clicked into the catch {} and add the exception handling. That’s a lot of pointless mouse and keyboard work. Now, using the keyboard, I would select the line of text (Shift-End to select to the end of the line), then Ctrl-K,S to bring up the Surround-with snippets, then type try and press Enter to surround my code with a try/catch block and automatically position the cursor in the catch {} block ready to select my exception type. Intellisense camel-case matching helped, so I only had to type in CE to match the ConstraintException I was trying to catch, hit Enter, and job done.

There are only so many hours in the day - reclaim yours by learning how to use the tools you have to get more done in less time.

Thursday, March 24, 2011

Synchronicity Part 2

Last year, it was Flash crashing Safari while I was trying to read an article about the problems with Flash. This time, it’s Google Chrome crashing while I’m trying to read about why the newly-released Firefox 4 is the new hotness.

image

Coincidence or conspiracy?

Tuesday, March 22, 2011

Unity and log4net

In my current project at TouchStar, I’ve had the opportunity to play with Unity, Microsoft’s Inversion-of-Control container. Previously I’ve used StructureMap, which is very popular, but I wanted to broaden my experience of different containers, and given that my project involved a WPF client, Unity seemed to be a good choice.

One of the first problems was how to configure log4net using Unity. Usually, log4net is called from within a class thusly:

   1: public class MyClassWithLogger()
   2: {
   3:     private static readonly ILog Logger = LogManager.GetLogger(typeof(this));
   4:  
   5:     public void DoAction()
   6:     {
   7:         Logger.Debug("Hello world");
   8:         DoSomeOtherAction();
   9:     }
  10:  
  11:     private void DoSomeOtherAction()
  12:     {
  13:         Logger.Debug("Still here");
  14:     }
  15: }

Which, depending on how you’ve configured your appenders, would produce an output something like this:

   1: MyClassWithLogger [DEBUG] - Hello world
   2: MyClassWithLogger [DEBUG] - Still here

So far, so vanilla, and the sort of code that anyone whose used log4net will have written thousands of times; but what happens if we want to apply good SOLID design principles and inject the log4net dependency into the class, rather than have the class create the instance itself. I prefer constructor injection for this, as it makes it very explicit what the dependencies are, and you can’t accidentally forget to set one without getting a compile-time error. The class would then become:

   1: public class MyClassWithLoggerDependency()
   2: {
   3:     private static readonly ILog Logger;
   4:  
   5:     public MyClassWithLoggerDependency(ILog logger)
   6:     {
   7:         Logger = logger;
   8:     }
   9:  
  10:     public void DoAction()
  11:     {
  12:         Logger.Debug("Hello world");
  13:         DoSomeOtherAction();
  14:     }
  15:  
  16:     private void DoSomeOtherAction()
  17:     {
  18:         Logger.Debug("Still here");
  19:     }
  20: }

We’re now ready to apply some IoC magic with Unity to create the instance of ILog that our class will use. Since log4net uses its own factory class to instantiate itself, we have to jump through a hoop or two to get Unity to set things up properly:

   1: public class Program
   2: {
   3:     public static void Main(string[] args)
   4:     {
   5:         var container = new UnityContainer()
   6:             .Register<ILog>(new InjectionFactory(x => LogManager.GetLogger(typeof(this))));
   7:             .Register<MyClassWithLoggerDependency>()
   8:  
   9:         var myClass = new container.Resolve<MyClassWithLoggerDependency>();
  10:         myClass.DoStuff();
  11:     }
  12: }

Which produces an output like this:

   1: Program [DEBUG] - Hello world
   2: Program [DEBUG] - Still here

See the problem? Now the logger is using the context of the code where Unity was configured to log from, rather than the context that the logger is being called from. I’ve seen plenty of questions asked about this, but it was only today that I stumbled upon the answer to this problem, hidden in a discussion on the Unity forums. A developer named Marco posted his solution, which was to create two extensions – the first being a BuildTracking extension, and the second being a LogCreation extension. The build tracking extension keeps tabs on what types are being built up, and then calls out to the log creation extension to create the logger component in the context of the class which is asking for it. Another developer, Scott, then posted his amendments that took care of some breaking API changes from the earlier version of Unity that Marco was using, together with an enhancement to improve detection of the calling class name when log4net is not being used with dependency injection.

My small contribution to the discussion was to provide the actual implementation code, which is as follows:

   1: public class Program
   2: {
   3:     public static void Main(string[] args)
   4:     {
   5:         var container = new UnityContainer()
   6:             .AddNewExtension<BuildTracking>()
   7:             .AddNewExtension<LogCreation>()
   8:             .Register<MyClassWithLoggerDependency>()
   9:  
  10:         var myClass = new container.Resolve<MyClassWithLoggerDependency>();
  11:         myClass.DoStuff();
  12:     }
  13: }
Now that in my eyes is a much tidier piece of code. Gone is the explicit registration of the ILog type with its rather ungainly use of the InjectionFactory to create the appropriate implementation, and instead we have the two new extensions registered.

This is a great little bit of code, and big thanks go to Marco and Scott for sharing their contributions with us. I’m sure that many other developers will find this useful.

Monday, March 21, 2011

Watching Ideas Take Flight

In my last entry, I mentioned an idea I’d had before on how to make it easier to package .NET applications when run as part of an automated build. It solved a problem for me, and I thought it worth sharing, firstly as an aide mémoire for myself, and secondly because it seems the sort of thing that other people would find useful.

Rob Reynolds came across my post, and he obviously found it useful. In fact, he liked it so much that he has put together a NuGet package to make the set-up of _PublishedApplications even easier, together with a demo of how easy it is to use.

Demo of _PublishedApplications at work

I’m thrilled to see this getting out there – a big thanks to Rob for really getting this off the ground, as well as giving it more exposure.

Thursday, March 10, 2011

Publishing .NET Applications

This is a problem I came across in my previous job at Fairfax Digital, when setting up automated builds; now that I am working at TouchStar, I’m facing the same problem, but couldn’t remember what I did the first time round.

The problem is this: when building ASP.NET web applications using TFS or some other continuous integration solution (I’m using UppercuT at TouchStar), the MSBuild engine very conveniently creates a _PublishedWebsites folder in your output folder, and then creates a subfolder in that folder for each website that you are creating. So far, so good. However, when building executable applications, such as console apps, WPF applications or Windows services (and I’m building all three at TouchStar) then it just throws everything into one directory, and leaves it to you to pick out the bits you need. “If only you could export your build results to a _PublishedApplications folder!”, I hear you cry.

Well, that’s essentially my solution. I took a copy of the Microsoft.WebApplication.targets file that is referenced in the ASP.NET project file, renamed it to Microsoft.Application.targets and saved it to C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Applications. I then tweaked it, renaming variables and such to match the type of content, and removing any references to /bin folders. I then reference the new file in the Visual Studio project file by adding the following line:

  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Applications\Microsoft.Application.targets" />

And voila! I now have one folder per application in the _PublishedApplications folder when run as part of an automated build. If I build from within Visual Studio, outputs are still sent to their usual location (e.g. /bin/Debug/). I’ve included a link to the file below.

[Download Microsoft.Application.targets]

Thursday, August 12, 2010

Mixing TFS 2008 and VS 2010

At work, we’re in the early phases of migrating our TFS 2008 setup to TFS 2010. However, since some teams have already started work on the new hotness that is VS 2010 and .NET 4, there was a need for us to get their automated builds up and running immediately. We “requisitioned” a desktop that was already running builds for another semi-defunct project using CruiseControl.NET, and installed Team Build on it.

It took a few tweaks to get the code compiling, but something was wrong with the testing phase – the tests would run, but the test runner would then report a failure, resulting in a yellow warning lights rather than nice green success lights. The error message was:

MSBUILD : warning MSB6003: The specified task executable "MSTest.exe" could not be run. The system cannot find the file specified [D:\Source\CommonPlatform\Common Platform Development CI Build\BuildType\TFSBuild.proj]

So the tests all passed, but then Team Build couldn’t find the testrunner that it had just used! We tracked down another user with the same complaint on StackOverflow, but they were shouting in the dark, with no response to their question.

After much head-scratching alternated with banging our heads against the wall and wondering why Microsoft products are sometimes to great and sometimes so plain awful (often in the space of just five minutes), we eventually found the solution to our problem tucked away in forum on MSDN. The TeamBuild targets file which imports the TestToolsTask has an invalid path reference:

<UsingTask TaskName="TestToolsTask" AssemblyFile="$(MSTestRefPath)\Microsoft.VisualStudio.QualityTools.MSBuildTasks.dll" 
Condition="'$(ProjectFileVersion)' == '2'" />

since MSTestRefPath doesn’t appear to be defined in VS 2010. By changing it to the correct path, the test runner can be found again, and the error disappeared.

Quite why Microsoft implemented it so that the tests would run but then fail afterwards I don’t know, but at least our builds are all happy, and the developers are happy. Hopefully we can now get back to migrating TFS 2008 to 2010, and we can see the back of this problem.

Wednesday, May 12, 2010

Synchronicity

Apple and Adobe seem to be having a bit of a dummy spit over Flash at the moment, which is polarising the developer community. Well, I opened up Google Reader to read Richard Banks’s latest thoughts on the subject, and as I do that, bam! Safari crashes with a Flash error.

Flash Irony

(the Flash app was running in a different tab, not as part of Google Reader).

Thursday, November 05, 2009

Working with bugs

No, this is not a post on entymology; rather, it’s a bit of a lament on the lost art of filing bug reports. Though they may bestride the programming world like a colossus, even the best programmers will eventually leave bugs in their code. Sooner or later, some poor user will fall foul of it.

You then have a number of solutions, depending on where the product came from. For a commercial product, you can:

  1. ignore it and hope it goes away;
  2. file a bug report, and hope that the provider will fix it;
  3. find some sort of workaround, or just learn to live with it;
  4. vote with your wallet, and switch to a competitor’s product

For an open-source product,, you have an extra option:

  1. download the source code, and fix it yourself, and preferably submitting your fix back to the community.

In my case, it was a bug in a Microsoft development tool, the succinctly named Microsoft Visual Studio Team System 2008 Database Edition GDR R2. As an aside, let me say that I’ve been using it for all of 2 days, and I absolutely love its functionality. It finally makes versioning and deploying databases a delight rather than a painful chore. There is now no excuse for organisations not to have their databases under version control, or for having painful manual deployment processes.

Anyway, it has a bug in it which is holding up a particular project at work. I searched for a solution, and found someone who had reported the same issue some 9 months ago. Unfortunately the bug report that they filed was so lacking of information that Microsoft promptly closed the bug as Not Reproducible. In fact, it’s not 100% certain that the bug relates to my issue because it is so light on details – it just reports the same error message.

As it happens, the steps required to reproduce the bug were incredibly trivial, so I opened a new bug, and gave the sort of details that a developer trying to fix a bug needs to see – in other words, I described what I was doing, what I expected to see happening, and what actually was happening. More to the point, I list the steps that the developer should take to make the same thing happen for them.

The first step to being able to resolve a bug is to be able to reproduce it. If you can’t reproduce it, how can you work out what is going wrong, and how can you prove that you’ve fixed the bug? And if the bug reporter doesn’t tell you how to reproduce the bug, what chance do you have of being able to fix it?

So please – if you want your bug to be fixed, consider the poor developer who has to fix it, and tell them what they need to know to get the job done. Anything less, and you’ll have a 9 month wait before someone else with the same problem files the same issue again.

Monday, June 29, 2009

iPhone on 3

When the iPhone 3G was originally released in Australia, I and many others complained that 3, who provide some of the best 3G data plans in the country, did not sell it. There were ways around it,which kind of suggest that it was a problem at Apple's end rather than 3's, but it seems that with the release of the updated iPhone 3GS, users of the 3 network are finally getting some Apple love. And of course, it's at this point that I notice that my elderly Nokia N95 8Gb is finally fully supported by OS X, including syncing from iTunes and iPhoto. Now where was that a year ago when I really needed it? Never mind; just as soon as I can sell a kidney on Ebay, I'll have his'n'hers iPhone 3GS's, and the Nokia can go in the phone recycling bin.

Tuesday, March 31, 2009

MassTransit

Earlier this month, I mentioned the MassTransit project, an open-source .NET Enterprise Service Bus implementation, a topic sure to break the ice at a many a party.

We've been getting stuck into MassTransit at work for a major project, and had all sorts of problems along the way, mainly due to the youth of the project and the general lack of documentation. Where there were code samples, sometimes the code just plain didn't work.

Blog postings need images, apparently; so here's one that's distantly related to the topic under discussion - it's a restaurant tram in MelbourneThe two main developers, Dru and Chris, have been a fountain of knowledge and general helpfulness, responding quickly to my sometimes continuous barrage of questions, not helped of course by our being on opposite sides of the planet. I've been able to chip in with the occasional patch, nothing to fancy at this stage, but at least enough for me to feel like it's not a completely one-way street.

Anyway, congratulations to MassTransit for shipping their v0.6 release candidate. I've been running it for a few days now, although without using some of the cooler pieces of new technology, such as the saga state machines. Hopefully with their help, I'll be able to get our project back on track and heading in the right direction.

Thursday, March 12, 2009

This stuff is supposed to be fun

So blogged Jeff Attwood some 18 months ago, and as far as my own experience goes, he is absolutely right. When I went to university, it was to study Electronics and Communications Engineering, but by mid-way through the second year, I really wanted to on Computer Science, but really it was just too late to be changing courses, so I stuck it out to the end. To show willing, I applied to some of the major electronics companies like Philips and Marconi, but nothing came of that, so I managed to convert my summer job at the Foreign & Commonwealth Office into a more permanent job, doing typical admin stuff in the library. A healthy dose of luck and good timing saw me slide into an IT helpdesk/sysadmin role, and from there, I never looked back.

I was then able to leverage (how I hate that word) my IT skills to get into development, and there I knew that I had found my real métier. Like no doubt thousands of my technical colleagues, I have found the perfect union between my favourite pastime and my job. My wife still marvels that I spend eight or more hours a day at the office working with computers, and then when I come home, I'm happy to spend the rest of the evening, or most of the weekend, doing exactly the same thing (and not getting paid for it!).

In fact, I enjoy being a developer so much that I will do everything in my power to avoid promotion to a position where I can't sit down and write code every day. For some, it may be just a step on the ladder to management, and that's OK; but for me, the day I stop coding and using computers is the day they prise the keyboard from my cold, dead hands.

In short, I know what colour my parachute is; and being a self-professed geek, it's black.

So are there any other categories of people out there whose private life seems to be just an extension of their working life? Or perhaps even better, they see it as the other way round, where they're getting paid to do something they could spend every day doing? Musicians? Sportsmen? Accountants, anyone?!

Wednesday, February 18, 2009

Cuuuurses!

Oh well, so much for my earlier optimism - it turns out, that for the time being at least, Sandcastle can't easily be used on a build server.

The problem is the Help 2.0 Compiler, which in a previous life as the Help 1.x Compiler, was shipped as a standalone product. However, Microsoft, in its infinite wisdom, decided to bundle the 2.0 version into the Visual Studio SDK; and of course, to install the Visual Studio SDK, you need to first have an installation of Visual Studio, which rather defies the point of a build server. Especially for small operations on a budget, having to acquire an extra VS license just to automate the creation of documentation is more than a pain in the neck, it's downright unsociable.

There are some guides on working round this, but they only cover up to VS2005 and its SDK, whereas we're using VS2008 SP1.

I'm going to have a play around with exporting chunks of my registry which has references to the 2.0 compiler, in the hope that that fixes things. I don't hold out much hope.

Friday, February 13, 2009

Catching Up

It's been a while since my last release of SvnRevisionLabeller, and I've not paid the project pages too much attention, seeing as everything was very quiet. Unfortunately, I hadn't set up the project to notify me whenever issues were raised, so I'd missed the raising of several bug or change requests.

Well, after stumbling upon one such change request during an unrelated Google session, I thought I'd better catch up on my project maintenance; it doesn't look very professional when your projects have bug reports unloved, unacknowledged, and unresolved.

The biggest change is that build number will be configurable; it was one of the first feature requests, and for a current project at work, it's something I wanted to do anyway.

BTW if you have downloaded and installed the plugin, I'd be interested to know. Google reports 822 downloads; the person who filed that request has linked to their site, so that's one, and of course I use it at Fairfax Digital, so that's two. Anyone care to offer up any of the other 820 downloads?!

Wednesday, February 11, 2009

Using Sandcastle with CruiseControl.NET

For a new project at work, I'm adding automatically-generated API documentation as part of my nightly build. Back in the days of .NET 1.1, we had the NDoc project, and explicit support for it in NAnt. Unfortunately, the project never made the transition to .NET 2.0, instead coming to a rather bitter and public end due to predominantly a lack of community support (despite the large numbers of downloads). I guess it's one the main failing of open-source projects - many are happy to take, but not so happy to give (whether money or time/effort).

Sandcastle is Microsoft's official documentation generator, but even three years on, it lacks some of the user-friendliness that any NDoc user had come to expect. The Sandcastle Help File Builder tool goes a long way to rectifying this, but most of the focus is on the GUI tool. Until the current v1.8 release, command line builds were taken care of by the SandcastleBuilderConsole.exe tool; however, the latest release drops this, and instead uses MSBuild, which ships with the .NET Framework. This is a rather nice touch, in my opinion - a clever use of existing tooling, rather than writing another new tool.

However, the documentation about using it in a continuous integration environment is still a little lacking, so I'm documenting here the problems I came up against.

Installation

So far, it seems like neither Sandcastle nor SHFB have been designed with easy deployment in mind. I like to include my build tools within my source repository; this saves a lot of tedious installation and configuration whenever setting up a new developer PC. Both tools come as MSI packages, with Sandcastle deploying as a 220Mb install, so maybe that one you can do without in your repository! SHFB on the other hand is relatively lightweight, at around 3Mb for the files required by the build tasks. You will need to set an environment variable for it to run properly, though:

<setenv name="SHFBROOT" 
   value="${Sandcastle.dir}" 
   unless="${environment::variable-exists('SHFBROOT')}" 
   verbose="true" />

The SHFB files that you seem to require are:

  • ColorizerLibrary.dll;
  • ICSharpCode.TextEditor.dll;
  • SandcastleBuilder.Components.Config;
  • SandcastleBuilder.*.dll;
  • SandcastleHelpFileBuilder.targets;

You'll also need the Help 2.0 Compiler tool hxcomp.exe, which ships as part of Visual Studio 2008 SDK; and of course, the SDK requires that Visual Studio 2008 is installed before it itself will install. Fortunately, you can pull out the contents of C:\Program Files\Common Files\Microsoft Shared\Help 2.0 Compiler\ and add that to your repository as well, bypassing that little pain-in-the-neck.

Configuration

To use SHFB within CC.NET with NAnt, you'll need the <msbuild> task that comes with NAntContrib. The syntax is as follows:

<msbuild project="${source.basedir}\Documentation.shfbproj">
   <arg value="/property:${HxComp.dir}" />
   <arg value="/property:SandcastlePath=C:\Program%20Files\Sandcastle\" />
</msbuild>

All the properties listed in the SHFB GUI tool can be set as above - just watch out for the need to escape spaces when hard-coding paths, which had me stumbled for an hour or two, until I found a post asking the same question.

Still To-Do

The one thing I really want to get done is programatically set the assemblies which will be documented; at the moment, you either use the GUI tool and relative paths, or edit the SHFB project file by hand. You could probably also use NAnt's <xmlpoke /> task to edit it, but I would prefer to be able to set it via parameters to the <msbuild /> task, so watch this space while I work it out.