Checking build durations over time

Wednesday, 18 May 2011

I’ve written a PowerShell script to iteratively grab changesets from TFS, and do a build of the solution from that changeset. For each build I record the time taken. This is useful if you think builds are taking longer than they used to and you need some quantitative evidence. You can save the output to a CSV file and open it up in Excel to display a pretty graph etc.

To use the script, you’ll need to have installed the Team Foundation Server Power Tools which include PowerShell cmdlets for TFS.

\# Iteratively build changesets from TFS to measure build speed
# Run this from a folder that is mapped as the TFS workspace

# Load VSVARS.BAT (From
function VsVars32()
    $vs100comntools = (Get-ChildItem env:VS100COMNTOOLS).Value
    $batchFile = \[System.IO.Path\]::Combine($vs100comntools, "vsvars32.bat")
    Get-Batchfile $BatchFile

function Get-Batchfile ($file) {
    $cmd = "\`"$file\`" & set"
    cmd /c $cmd | Foreach-Object {
        $p, $v = $\_.split('=')
        Set-Item -path env:$p -value $v


# Get changeset history since 1-Jan-2011 and checked in by me
$history = Get-TfsItemHistory "$/Project/Branch" -Version "D01/01/11~" -Recurse | Where-Object { $\_.Owner -eq "DOMAIN\\username" }

# Process changesets from earliest to latest

$tf = "C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE\\TF.exe"

$history | % {
    & $tf get /version:C$($\_.ChangesetId) /Recursive /Overwrite /NoPrompt 2>&1 | Out-Null

    # clean first
    & "msbuild.exe" /t:Clean /noconlog /v:q /nologo 2>&1 | Out-Null

    # build
    $duration = Measure-Command { & "msbuild.exe" /noconlog /v:q /nologo  }

    if ($LastExitCode -eq 0)
        Write-Output "$($\_.ChangesetId), $($duration.TotalSeconds)"
    else {
        Write-Warning "$($\_.ChangesetId) build failed"

Visual Studio network performance with TFS through a VPN

Monday, 9 May 2011

I’ve been accessing a TFS server remotely through a VPN connection. I’d noticed that the performance was not that great, and then discovered this suggestion to specify the defaultProxy element in the devenv.exe.config file.

That worked pretty well, but I noticed that things were still a bit sluggish, so added a bypasslist element too, to ensure that anything on a network doesn’t use the proxy either. That’s working nicely now.

<?xml version=”1.0” encoding=”utf-8”?>

                   <proxy bypassonlocal="True" proxyaddress=[http://proxy-server:8888](http://proxy-server:8888)/>                    

Updating multiple lines in Visual Studio project files

Wednesday, 4 May 2011

A while back I blogged about how to change text from a single line in a Visual Studio project file. What about when you need to replace a number of lines of text? This worked for me:

$regex = new-object Text.RegularExpressions.Regex “\<Target Name=`“AfterBuild`”\>.+\</Target\>”, (‘singleline’)

Get-ChildItem -recurse -filter “*.*proj” % { $text = (Get-Content $_.FullName) -join “`r`n”; $regex.Replace($text, “<Import Project=`”`$(SolutionDir)\Module.targets`” />`r`n”) Set-Content “$($_.FullName).tmp” }

We have to do a little more work compared to the first approach. We need to join all the individual lines into one single line so that the regex will operate correctly. Because we want to set options on the regex, we create that separately too. Note that the above example writes to a new .tmp file, so you can confirm the replace is working properly before overwriting the original files.

Project files are just XML files, so this technique should work for any XML file.

In my case, the solution was checked in to TFS, so the project files will need to be checked out before they can be updated. The checkout can be incorporated into the pipeline like this:

Get-ChildItem -recurse -filter “*.Service.*proj” % { & “C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\TF.exe” checkout $_.FullName; $text = (Get-Content $_.FullName) -join “`r`n”; $regex.Replace($text, “<Import Project=`”`$(SolutionDir)\Web.Module.targets`” />`r`n”) Set-Content “$($_.FullName).tmp” }


Assuming culture

Tuesday, 26 April 2011

I’ve just had an interesting bug report for Aussie Toilets. The stack trace starts with this:

System.Reflection.TargetInvocationException: TargetInvocationException —> System.FormatException: FormatException à System.Decimal.Parse(String s, NumberStyles style, IFormatProvider provider) à Gardiner.PublicToilets.Services.DataService.b\_\_3(XElement x)

There’s a small clue there, but the other big hint was the user’s regional setting:

Culture: fr-FR

It turns out in a number of places I’d been assuming the default number format, particularly instances of Decimal.Parse(), Convert.ToDouble(), and the popular String.Format().

So if you’re in France, you’d be used to seeing “123.49” written as “123,49”. The bug in the application was that the data being read was originally formatted in the former, but with the user’s regional settings set to ‘French (France)’ the parsing methods were assuming it would be formatted as the latter.

I’ve resolved the problem in this instance by explicitly specifying the InvariantCulture, as the data isn’t displayed to the user. If it were intended for user display, then allowing the user’s regional settings to influence the display would be quite appropriate.

FxCop (aka Visual Studio Code Analysis) will warn you about these kinds of issues, specifically CA1305 – Specify IFormatProvider. I’ve changed this warning (and a few others) to an error to ensure I don’t get caught by it again.

Visual Studio Code Analysis Settings - changing warnings to errors

Expect Aussie Toilets v1.4 soon!


When I first started working on Aussie Toilets, I was doing it from the perspective of a parent who has had first-hand experience trying to find a public toilet for a young child. I hadn’t really considered another market for the app might be the overseas visitor. Maybe I should consider providing translations for some of the labels for these users too.

Aussie Toilets app v1.2

Thursday, 21 April 2011

‘Aussie Toilets’ version 1.2 is now available in the Windows Phone marketplace. This is my Windows Phone 7 app that shows the nearest public toilets to your current location. wp7_278x92_blue The latest release includes the April 2011 dataset, and significant performance improvements. Specifically, toilet locations should load almost instantly. So now if you’re in a hurry to find the nearest public toilet, you’ll be relieved (ha ha) to know you won’t be kept waiting any longer than necessary. I’m quite chuffed that ‘Aussie Toilets’ is currently sitting at no. 3 in the top selling apps of the ‘Navigation’ category in Zune. Not sure if this is just for Australia or global. So far I’ve had over 1,200 downloads, which isn’t too bad at all. PS. I have received a bug report from an Austrian user of Aussie Toilets – turns out I hadn’t tested the app outside Australia! This may explain an issue I had with getting 1.2 passing the Marketplace requirements (as I assume the testing would be taking place in North America). So expect v1.3 very soon!

Update 24th April, 3.30pm Version 1.3 is now available in the marketplace