mandag 7. desember 2009

Changing TFS emails to link to Team System Web Access – Part 2 - Visual Studio Team System (VSTS) Blog - by Neno Loje

Neno Loje stated in Changing TFS emails to link to Team System Web Access – Part 2 - Visual Studio Team System (VSTS) Blog - by Neno Loje that:

"There are four areas to look at:
Work Item notification mails (has already been discussed here)
Build notification mails
Check-in notification mails
Mails sent by Team Explorer (feature of TFS 2008 SP1)
Area 1 is part of a separate blog post, for Area 2 there are currently no equivalent steps (as stated in KB956761)."

I just couldn't live with it so I made it work, like this in BuildCompletionEvent2.xsl:

   1:        <div class="Title">

   2:          <xsl:call-template name="link">

   3:            <xsl:with-param name="format" select="'html'"/>

   4:            <xsl:with-param name="embolden" select="'true'"/>

   5:            <xsl:with-param name="fontSize" select="'larger'"/>

   6:            <xsl:with-param name="link" select="concat(substring-before(Url,':8080/Build/Build.aspx?artifactMonike'),':8090/UI/Pages/Build/Details.aspx?builduri=vstfs%3A%2F%2F%2FBuild%2FBuild%2F',substring-after(Url,'artifactMoniker='))"/>

   7:            <xsl:with-param name="displayText" select="Title"/>

   8:          </xsl:call-template>

   9:        </div>

Where the point of the matter is line 11. The change was inspired by the original post by Neno and a simple fix.

To add even more we even changed it a bit more to include a link to a report over the failing tests for the last 72 hours. I am not showing the report part, but the take-away is the inclusion of the link:


   1:  <xsl:if test="StatusCode != 'Succeeded'">

   2:     <tr>

   3:       <td class="PropName">Build Log Location: </td>

   4:       <td class="PropValue">

   5:         <xsl:call-template name="link">

   6:           <xsl:with-param name="format" select="'html'"/>

   7:           <xsl:with-param name="embolden" select="'false'"/>

   8:           <xsl:with-param name="link" select="LogLocation"/>

   9:           <xsl:with-param name="displayText" select="LogLocation"/>

  10:         </xsl:call-template>

  11:       </td>

  12:     </tr>

  13:     <tr>

  14:       <xsl:call-template name="link">

  15:         <xsl:with-param name="format" select="'html'"/>

  16:         <xsl:with-param name="embolden" select="'true'"/>

  17:         <xsl:with-param name="fontSize" select="'larger'"/>

  18:         <xsl:with-param name="link" select="concat(substring-before(Url,':8080/Build/Build.aspx?artifactMonike'),'/ReportServer/Pages/ReportViewer.aspx?/Confirmit/Failed+Tests&rs%3aCommand=Render&BuildParam=',substring-after(Url,'artifactMoniker='))"/>

  19:         <xsl:with-param name="displayText" select="'Report on failing tests in this build'"/>

  20:       </xsl:call-template>

  21:     </tr>

  22:   </xsl:if>

The added code is the lines 13 – 21.

Happy coding

onsdag 19. august 2009

Update: Why it is an error for MSBuild to build clean in the same order as it builds regularily

In the two postings listed below I described how MSBuild is building the Clean target of a VS Solution in the wrong order.

Brumlemann: Why it is an error for MSBuild to build clean in the same order as it builds regularily

Brumlemann: MSbuild of VS solution under target clean is just plain wrong

I also created a Microsoft Connect issue on this behaviour and you can find that posting here:

Brumlemann: MSBuild builds the clean target of VS solution files in the wrong order

The Visual Studio team at Microsoft has since reckognized this as a bug and, as the connect issue shows, a fix has been reported to have been implemented for the next release of VS2010. At the time of writing it is post beta 1, so I guess beta 2 is 'next release'. I will be sure to verify this and report back on my findings.

lørdag 21. mars 2009

Analyzing the code base of CruiseControl.NET - Patrick Smacchia [MVP C#]

Analyzing the code base of CruiseControl.NET - Patrick Smacchia [MVP C#]

Once again Patrick delivers a good blog. His favourite is picking apart popular standard libraries. This time it's CruiseConrol that gets a runthrough.

The reason why I wanted to mention this post is that he sneaks in another topic that we agree strongly on, and even possitively feel a bit passionate about, namely
Copy Local
in Visual Studio project/Solutions. I had planned to blog about why this is a bad idea myself, but Patrick beat me to it. I guess beeing not so entangled in corporate life gives him the oppurtunity to set aside some more time to put things straight. Well done Patrick (again :).

Build task for searching in files

Technorati Tags: ,

Just to test out the code add-in I just added to Live Writer I thought I would share this little build task for filtering out files based on standard string search, with or without regular expressions. Disclaimer! The regular expression mode didn’t work as I had expected and my needs there and then didn’t exceed pure freetext search, so it may need some tweaking, and of course the usual use at own risk bla bla.

namespace YourNameSpace.BuildTasks
using System.Diagnostics;
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Utilities;
using System.Text.RegularExpressions;
using Microsoft.Build.Framework;

/// <summary>
/// Finds files with a content that has one or more matches
/// for the pattern provided.
/// </summary>
public class FindFilesWithContent : Task
public FindFilesWithContent()
results = new List<TaskItem>();
} // Properties
public ITaskItem[] FilesToSearch { get; set; }
public string Pattern { get; set; }
public bool UseRegExp { get; set; }
private readonly List<TaskItem> results;
public ITaskItem[] Results
get { return results.ToArray(); }
public override bool Execute()
if(UseRegExp) Log.LogMessage(MessageImportance.Low,
"Using regular expression", new object[] { null });
"Matching with pattern {0}", new object[] { Pattern });
foreach (ITaskItem taskItem in FilesToSearch)
if (!File.Exists(taskItem.ItemSpec))
Log.LogError("File does not exist: {0}",
new object[] { taskItem.ItemSpec });

//Read the whole text file to the end before closing it
StreamReader reader = new StreamReader(taskItem.ItemSpec);
string allRead = reader.ReadToEnd();

"Content of file to match: {0}",
new object[] { allRead });

//Do the matching
if (Compare(allRead, Pattern))
results.Add(new TaskItem(taskItem));
"File matched: {0}",
new object[] { taskItem.ItemSpec });
"File did not match: {0}",
new object[] { taskItem.ItemSpec });
return true;

private bool Compare(string stringToSearch, string pattern)
if (UseRegExp)
return Regex.IsMatch(stringToSearch, pattern);
return stringToSearch.Contains(pattern);

The usage is as follows:

<!--UseRegExp="false" is default-->
Pattern="This string I will find"
<Output TaskParameter="Results"

Blogging - Add-on galleri

Just installed IE8 and researching some of the new features. As a consequence I started using Live Writer. Time will tell if this is the cool way to blog. Seems nice enough though. Let’s try to add a picture


Not exactly flattering but a test is a test. Now you all know what I look like, when I have worked to much overtime ;-)

Blogging - Add-on galleri

mandag 19. januar 2009

Challenges with TypeMock and Team Build

According to the TypeMock documentation it's a breeze to set up mocking during Team Build. Well I have just spent a week trying to get it to work and I think I finally cracked it. It all comes down to reading the f*** manual and believing it to be taken literally.


TypeMock location

The TypeMock manual say the following:
<!-- Use Typemock Isolator MsBuild Extensions -->
<Import Project="C:\Program Files\TypeMock\Typemock Isolator\TypeMock.MSBuild.tasks" />

<!-- Override this target to plugin custom tasks before running tests -->
<Target Name="BeforeTest">
<!-- Start TypeMock -->

<!-- Override this target to plugin custom tasks after running tests -->
<Target Name="AfterTest">
<!-- Quit TypeMock -->

Well first of all this isn't quite true. As of 5.1 (I think) TypeMock installs into another directory (C:\Program Files\Typemock\Isolator\5.2 in my case as we just upgraded to 5.2.1).  So you have to perform some trickery in your MSBuild files to detect whether your doing a build server or desktop build. Luckily there are ways to do this.

Anyway, this is not my main point. The main point is that you can get tricked by the way MSBuild is implemented and used during an EndToEndIteration build.

Where does the TypeMockRunner instance live?

What I saw was that my tests were running fine during DesktopBuild but failing miserably during E2EI (yes I ran a desktop build (msbuild TFSBuild.proj /t:test) on the build server and the tests ran fine). So that’s what I've been spending the last week trying to unravel. And here are the results from the Norwegian jury:

You must follow the instructions (above) from the TypeMock doc to the extent that you call TypeMockStart/TypeMockStop from TFSBuild.proj itself.

We have an existing build system (CruiseControl) so I was reusing my Test.proj calling the necessary targets from inside that. THIS WILL NOT WORK IN A TEAM BUILD CONTEXT! You have to call TypeMockStart from the same instance of MSBuild as the one you're running tests from (i.e. calling MSTest/TestToolsTask)!

Consequence: The multiple agents switch (/m) of MSTest is incompatible with TypeMock.

I had to disable building in parallel because of this. It has to be said that the guys at TypeMock are waiting for me to have some available time so we can look into this since this is obviously no more good for them than it is for me. Ay ve! So much to deal with and so little time.