This blog has moved, permanently, to http://software.safish.com.

Tuesday, September 21, 2010

Prettify

Following stackoverflow’s example, I’ve started using prettify for syntax highlighting on this blog.  I’ve used the Google syntax highlighter in the past, but prettify just seems easier as I don’t need to mark it with class names or anything – all I need to do is wrap code in <pre> and <code> tags, and it just works.  It’s clever enough to work out the language.

Getting it working was really simple.  I downloaded the source, combined all the .js files into one using Google’s Closure Compiler, and update the .css file to the styles I like (stolen without shame from stackoverflow – I love that site).

To get the styles to apply to my blog, I also added an initialisation script to make the prettify call, and it works.  Hopefully this should save me some time in the future.

I found a really good article here that showed me how to set this all up.  I’ll update old blog posts at some stage, for now they’re going to appear without styling.

Wednesday, September 8, 2010

.NET – Detecting Modem COM Ports

We have a project at the moment where we’re using GSM modems attached to the local machine to send an SMS.  One of the issues we’ve had is when the modem is not actually connected before our service starts up: our service sometimes attaches to the COM Port that is required by the modem, and this prevents the modem from ever connecting.

There is a simple way to detect which COM ports are assigned to modems installed on your machine:

using System.Management;

ManagementObjectSearcher mos = new ManagementObjectSearcher("SELECT * FROM Win32_POTSModem");
foreach (ManagementObject mo in mos.Get())
{
    string s= mo["AttachedTo"].ToString();
}

Other properties available can be looked up here: http://msdn.microsoft.com/en-us/library/aa394360%28VS.85%29.aspx

Tuesday, August 31, 2010

Using the WiX Installer

I’ve been playing with the Wix Installer for the last few days, and I’m absolutely amazed by it.  It’s a real bastard to get into, but once you’re up and running it’s pretty incredible how much can be customised.  There is a LOT of documentation out there, but the most useful link I found was this tutorial – it really is worth your while to read the entire tutorial BEFORE trying to create your own installation project.

Instead of creating another tutorial, I thought I’d list the items that tripped me up.

Visual Studio 2010 Integration

I downloaded Wix 3.0 (64 bit), and after installation, it wasn’t available as a project within Visual Studio.  Download the beta version of 3.5 – it seems pretty stable and integrates with Visual Studio,.

No Wizard

No wizard!?  WTF!?  It turns out it’s XML-based – you end up doing a lot of the setup by hand.  Deal with it.

References in Visual Studio

You will probably require extensions so you can customise the UI, or perhaps ensure the user has a .NET Framework installed.  I’m working in Visual Studio 2010, and I wasn’t sure how to do this so I added compiler and linker options in the project properties.  You do not need to do this.  All you need to do is click “Add Reference” on the project, and select the extension from the list that appears.  For example, if you want to add the .NET Framework prerequisites, right-click References, and select WixNetFxExtension.  That is all you need to do.

Default UI

The default installation dialog really sucked, and it took me a while to work out that you need to specify a different UI type.  That’s what you get for not reading the above tutorial before creating your project.  You need to create a <UI> element, and specify the UIRef you want to use.

Dialog Sequence

Creating custom dialogs is pretty easy once you get the hang of it, but I struggled a little with navigation between dialogs.  Eventually I found the reference on the Wix site to a full list of Wix dialogs that you can navigate between at http://wix.sourceforge.net/manual-wix3/WixUI_dialogs.htm.

Using the IIS Extension (For deploying web sites)

This foxed me a little too.  Mostly, using the extensions just worked in Visual Studio, but the IIS extension doesn’t.  You need to add the namespace reference, something along the lines of:

<wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:iis="http://schemas.microsoft.com/wix/IIsExtension" xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension">

You can then use the extension elements as follows:

<iis:WebSite Id='DefaultWebSite' Description='Default Web Site'>
       <iis:WebAddress Id='AllUnassigned' Port='80' />
     </iis:WebSite>

Thursday, August 26, 2010

Unit Testing and DateTime Comparisons

 

One thing I’ve found annoying for the long time, is trying to assert DateTime equality when unit testing, particularly when the DateTimes have been parsed from strings in the underlying method.  Two DateTime constructs, despite being identical in terms of their values, often won’t assert as being equal and your unit test fails.  As such, you end up doing other sorts of tests, for example checking the individual values.

To help test dates, what I’ve done is created a helper class for asserting two dates are “equal”, to a specifed level of precision:

public static class AssertHelper
    {
        /// 
        /// Asserts that two dates are equal by checking the year, month, day, 
        /// hour, minute, second and millisecond components.
        /// 
        /// The current date
        /// 
        public static void AreDatesEqual(DateTime expected, DateTime actual, DateTimePrecision precision)
        {
            if (precision >= DateTimePrecision.Year && expected.Year != actual.Year)
            {
                throw new NUnit.Framework.AssertionException("Year in dates do not match as expected.");
            }
            if (precision >= DateTimePrecision.Month && expected.Month != actual.Month)
            {
                throw new NUnit.Framework.AssertionException("Month in dates do not match as expected.");
            }
            if (precision >= DateTimePrecision.Day && expected.Day != actual.Day)
            {
                throw new NUnit.Framework.AssertionException("Day in dates do not match as expected.");
            }
            if (precision >= DateTimePrecision.Hour && expected.Hour != actual.Hour)
            {
                throw new NUnit.Framework.AssertionException("Hour in dates do not match as expected.");
            }
            if (precision >= DateTimePrecision.Minute && expected.Minute != actual.Minute)
            {
                throw new NUnit.Framework.AssertionException("Minute in dates do not match as expected.");
            }
            if (precision >= DateTimePrecision.Second && expected.Second != actual.Second)
            {
                throw new NUnit.Framework.AssertionException("Second in dates do not match as expected.");
            }
            if (precision >= DateTimePrecision.Millisecond && expected.Millisecond != actual.Millisecond)
            {
                throw new NUnit.Framework.AssertionException("Millisecond in dates do not match as expected.");
            }


        }
    }

    public enum DateTimePrecision
    {
        Year = 0,
        Month = 1,
        Week = 2,
        Day = 3,
        Hour = 4,
        Minute = 5,
        Second = 6,
        Millisecond = 7
    }
This effectively allows me to unit test that the dates were close enough, without worrying to much about the exact equality. This solution, although working, somehow feels dirty. I'd love to know if anyone else has any better solutions for unit testing date equality in .NET.

Tuesday, August 3, 2010

ILMerge

I Used ILMerge today for the first time, and it's great. Aspnet_merge.exe is actually based on this tool, and it allows you to combine all your assemblies into a single exe or dll - great for simple deployment.

It gets installed by default to C:\Program Files (x86)\Microsoft\ILMerge, with fairly decent documentation. To consolidate a fairly simple Windows exe with three dlls into a single exe, all I did was the following:

ILMerge.exe /t:winexe /out:Output.exe /ndebug Program.exe Lib1.dll Lib2.dll Lib3.dll

Wednesday, July 28, 2010

Running MSBuild using Powershell Script

I wanted to build a Visual Studio solution using MSBuild using a Powershell script. Surprisingly, I couldn't find a reference on the web that actually worked for me. I thought I'd post it here for future reference, as it applies to the execution of any executable from within Powershell. It was "Invoke-Expression" that I hadn't used before.
 
$baseDir = "C:\Test\"
$outputFolder = $baseDir + "Output"
$msbuild = "C:\Windows\Microsoft.NET\Framework64\v3.5\MSBuild.exe"
$options = "/noconsolelogger /p:Configuration=Release"
$releaseFolder = $baseDir + "MyProject\bin\Release"

# if the output folder exists, delete it
if ([System.IO.Directory]::Exists($outputFolder))
{
 [System.IO.Directory]::Delete($outputFolder, 1)
}

# make sure our working directory is correct
cd $baseDir

# create the build command and invoke it 
# note that if you want to debug, remove the "/noconsolelogger" 
# from the $options string
$clean = $msbuild + " ""MySolution.sln"" " + $options + " /t:Clean"
$build = $msbuild + " ""MySolution.sln"" " + $options + " /t:Build"
Invoke-Expression $clean
Invoke-Expression $build

# move all the files that were built to the output folder
[System.IO.Directory]::Move($releaseFolder, $outputFolder)

Friday, May 14, 2010

Debugging log4net

I ran into an issue with log4net today where it just would NOT log to the database. I knew the database connection settings were fine, and the config file was fine, but some minor changes I had made to field sizes resulted in the whole thing not logging.
The problem is, log4net, for obvious reasons, doesn't raise exceptions when it fails, so short of downloading the source and debugging, I was at a bit of a loss. Luckily, those clever fellas have given a way to log internal messages! It's pretty straightforward:

Add the following in your App.config/Web.config, under the configuration section:
 
 <system.diagnostics>
    <trace autoflush="true">
      <listeners>
        <add
          name="textWriterTraceListener"
          type="System.Diagnostics.TextWriterTraceListener"
          initializeData="C:\temp\log4net.txt" />
      </listeners>
    </trace>
  </system.diagnostics> 
Then, add the following key to the appSettings section in your web.config:
  <add key="log4net.Internal.Debug" value="true"/>