Inside the Microsoft® Build Engine: Using MSBuild and Team Foundation Build

I’m proud to say that after many months of work Sayed Ibrahim Hashimi and I have completed work on Inside the Microsoft® Build Engine: Using MSBuild and Team Foundation Build (PRO-Developer). It is being published by Microsoft Press and is due out on 7th January 2009.

Allowing Users To Edit Destination Email Address in Reporting Services

When users subscribe to a report via email in Reporting Services the destination email address field defaults to their username and is read-only. If the SMTP server that you’re using won’t accept emails for plain usernames then you will have to allow users to enter their full email address when subscribing to a report.

To do this:

  1. Edit %ProgramFiles%\Microsoft SQL Server\MSSQL.3\Reporting Services\ReportServer\rsreportserver.config.
  2. Locate <SendEmailToUserAlias>True</SendEmailToUserAlias> and change True to False.
  3. Save the file and restart the ReportServer service.

Receiving TFS Events Using WCF

There are numerous examples around that explain how to receive TFS events using an ASMX web service. In this post we’ll look at how you can create a WCF service, hosted in IIS or self-hosted, to receive these events.

Prerequisites

  • Visual Studio 2008 with Service Pack 1
  • Team Foundation Server 2008

Create a WCF Service

The first step is of course to create a WCF service project. In Visual Studio 2008 create a new WCF Service Library using the language of your choice but in this example we’ll use Visual Basic .NET. If you do not see the WCF option select either .NET Framework 3.0 or .NET Framework 3.5 from the dropdown list in the top right-hand corner of the New Project dialog.

 image

This will create a project containing an app.config (which stores the WCF configuration), IService1.vb (which stores the service’s interface), and Service1.vb (which stores the service’s implementation). The new project should look like this:

 image

Renaming the Service Interface and Service Implementation

IService1 and Service1 aren’t the most descriptive names, so we’ll rename them to TfsEventSubscriber and remove the sample service implementation. To do this:

  1. Rename the file IService1.vb to ITfsEventSubscriber.vb.
  2. Open the file ITfsEventSubscriber.vb and rename the interface from IService1 to ITfsEventSubscriber.
  3. Remove the GetData and GetDataUsingContract functions.
  4. Remove the CompositeType class.
  5. Open the file app.config and replace any references to IService1 with ITfsEventSubscriber.
  6. Rename the file Service1.vb to TfsEventSubscriber.
  7. Open the file TfsEventSubscriber.vb and rename the class from Service1 to TfsEventSubscriber.
  8. Change the interface the class inherits from IService1 to ITfsEventSubscriber.
  9. Remove the GetData and GetDataUsingContract functions.
  10. Open the file app.config and replace any references to IService1 with ITfsEventSubscriber.
  11. Save all of the files and project and build the project to make sure we haven’t broken anything.

The resulting project should look like this:

 image

Define the Method to Receive TFS Events

The next step is to define a method that will receive the TFS Events. The name of this method is up to you but the convention is to call it Notify and it must accept two string parameters called eventXml and tfsIdentityXml. The eventXml argument will contain the XML about the event occur and this will conform to the schema for that particular event. The tfsIdentityXml argument will contain XML identifying the application tier that raised the event.

We now add this method to the ITfsEventSubscriber and apply the OperationContract attribute. We also need to specify the namespace and action named used by Team Foundation Server when calling this operation. This results in the interface looking like this:

<ServiceContract(Namespace:="http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03")> _

Public Interface ITfsEventSubscriber

    <OperationContract(Action:="http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify")> _

    Sub Notify(ByVal eventXml As String, ByVal tfsIdentityXml As String)End Interface

For the project to compile we must implement this new method in the TfsEventSubscriber which would then look like this:

Public Class TfsEventSubscriber
    Implements ITfsEventSubscriber

    Public Sub Notify(ByVal eventXml As String, ByVal tfsIdentityXml As String) Implements ITfsEventSubscriber.Notify

    End Sub
End Class

Writing the Implementation

You can now extend the Notify method to provide your service’s implementation. In our example we simply dump each request out as a uniquely named XML file:

Imports System.IO

Public Class TfsEventSubscriber
    Implements ITfsEventSubscriber

    Public Sub Notify(ByVal eventXml As String, ByVal tfsIdentityXml As String) Implements ITfsEventSubscriber.Notify
        File.WriteAllText(Path.Combine(Path.GetTempPath(), Guid.NewGuid.ToString() & ".xml"), eventXml)
    End Sub
End Class

Configure the WCF Service

There are a number of changes that need to be made to the WCF Service’s configuration, these can be made by editing the app.config file directly or by using the WCF Configuration Editor shown here.

 image

We need to change the binding from wsHttpBinding to basicHttpBinding.

 image

Because Team Foundation Server will never access the metadata service we can safely remove it from our configuration. Firstly we delete the endpoint that implements the IMetadataExchange contract.

 image

Then we remove the serviceMetadata behaviour:

 image

Testing and Debugging Your Service

If you run the project using Visual Studio it will automatically host your service using the WcfSvcHost that ships with Visual Studio 2008. While the project is running in Visual Studio then all of the usually debugging tools (such as breakpoints) will be available.

Once the service is running you can use BisSubscribe.exe from the Visual Studio 2008 SDK to add a subscription to Team Foundation Server so that your service is called when events are raised. In this example we add a SOAP subscription to the BuildStatusChangedEvent using the URL that Visual Studio hosted our service:

BisSubscribe.exe /eventType BuildStatusChangedEvent 

    /address http://DEVWORKSTATION:8731/Design_Time_Addresses/ReceiveTfsEventsUsingWcf/TfsEventSubscriber/

    /server http://TFSRTM08:8080/ 

    /deliveryType Soap

If you have a firewall, including the one that ships with Windows, you may need to disable it or add an exception for the port that the service has been hosted on.

Deploying Your Service

Once you’ve built and tested and your service you can host it using any of the hosting methods supported by WCF (such as using IIS or self-hosting) and then use BisSubscribe to add the necessary subscriptions.

TFS 2008 Service Pack 1 Bug Fixes

Brian Harry has published a list of bug fixes that shipped in TFS 2008 Service Pack 1. What I also found interesting from this list is the breakdown of where different bugs were detected or reported.

Suppressing Continuous Integration Builds Part II

I recently blogged about how you can suppress continuous integration builds by adding ***NO_CI*** to the check-in comment. It was pointed out to me on the OzTFS mailing list that there is a property in Team Build called $(NoCICheckInComment) that contains this value so you can avoid having to hard-code it in your build script.

Extending Team Foundation Server UI

I’ve been doing some work today on extending the Team Foundation Server UI, for example integrating with Team Explorer and the Pending Changes windows. I came across a number of resources explaining how to achieve this:

How to get the active Team Foundation Server and Project from an Add-In

Extending Team Foundation Server Version Control for Team Build Types Visual Studio integration

How to Write a Team Foundation Version Control Add-in for Visual Studio

Extending VSTS Work Item Tracking UI: Accessing work item UI elements and responding to events

Work Item Tracking v1 Client Extensibility in Visual Studio Team System

Modifying build emails to include Build Type

The emails sent by Team Build to notify that a build has completed don’t include the build type that spawned the build. This isn’t normally an issue because the default build numbers used include the build type. However, if you’ve overriden the build number generation you may want to include the build type within the email.

  1. On the Team Foundation Server navigate to %ProgramFiles%\Microsoft Visual Studio 2005 Team Foundation Server\Web Services\Services\v1.0\Transforms. This is where all of the email templates are stored.
  2. Back up the files BuildCompletionEvent.plaintextXsl and BuildCompletionEvent.xsl. These are the files we’ll be modifying.
  3. Edit the BuildCompletionEvent.plaintextXsl file.
  4. Immediately below the line Team Project: <xsl:value-of select=”BuildCompletionEvent/TeamProject”/> add the line Build Type: <xsl:value-of select=”BuildCompletionEvent/Configuration”/>.
  5. Save the file.
  6. Edit the BuildCompletionEvent.xsl file.
  7. Immediately below the section:

    <tr>
        <td>Team project: </td>
        <td class=”PropValue”><xsl:value-of select=”TeamProject”/></td>
    </tr>

    Add the section:

    <tr>
           <td>Build type: </td>
           <td class=”PropValue”><xsl:value-of select=”Configuration”/></td>
    </tr>

  8. Save the file.
  9. Back up the two files you modified. You should do this because when applying a Team Foundation Server service pack these files may be reverted to the original versions.
  10. Finally, restart IIS on the Team Foundation Server. You need to do this because these *.xsl files are cached the first time they are read and restarting IIS will refresh this cache.

That’s all there is to it. I haven’t tested this under Team Foundation Server 2008 (yet) but I expect the process will be the same. The more advanced reader will be wondering how I knew that the element that had to be selected was called Configuration, there are two parts to my answer:

  1. For each of the events there is an *.xsd file in that directory that specifies all of the elements that are available when that event fires. In this case it is the BuildCompletionEvent.xsd file that we’re interested in.
  2. When looking at that file the first element I chose was the one called Type (this seemed logical), however, in my testing this was always blank. After a bit of research I came across a post by Jason Prickett stating the Configuration is the correct element to use.

TFS 2008 SDK Missing

Brian Harry has pointed out that the TFS 2008 SDK was erroneously excluded from the VS 2008 SDK. They are working on rectifying this but recommend that in the meantime you continue using the TFS SDK in the VS 2005 SDK because there have been very few object model changes.

Schemas for Work Item Type Definitions

I’m doing a lot of work with Work Item Type Definitions and for those that don’t know the Visual Studio SDK includes schemas for these that can be used in Visual Studio (and other XML editors) to provide Intellisense capabilities.

Rob Caron blogs about this here. For those that don’t want to download the whole SDK he also provides a direct download of just the schemas.

Update to Team Foundation Server Power Tools (TFPT)

A new version of the Team Foundation Server Power Tools has now been released.

This version of the Power Tools is targeted at Visual Studio Team System/Team Foundation Server 2008 only so be aware that this version will not work with 2005.

In addition to support for 2008 this version also boasts a number of new and very useful features:

  1. Navigate to Windows Explorer which opens Windows Explorer to the folder corresponding with the current folder in the Source Control Explorer. Additionally, this can be bound to a keyboard shortcut!
  2. Find in Source Control which allows you to find items based on status or wildcards. Hopefully, we’ll see a version of this in the future that can search contents as well.
  3. Build Notification which is a system tray utility to notify you about the status of builds. Jim Lamb blogged about this some time ago.
  4. DestroyWI and DestroyWITD which allow you to remove work items and work item type definitions. This is invaluable if you are creating or customising your own work item types.
  5. The Process Template Editor can now be run standalone outside of Visual Studio.
  6. Annotate, TreeDiff, annd TestToolsTask have been removed because they’re now part of 2008.

Brian Harry discusses some of these features on his blog.