Programmatically finding a Stored Query Definition within TFS2010

Today I’m building a small utility and have a requirement to execute a stored work item query from within Team Foundation Server 2010. Previously I’d used the StoredQueries collection on the Project instance to find a query by name … however it would appear that this was depreciated as part of the TFS2010 release.

I was surprised to find that there doesn’t seem to be a simple replacement for finding a specified stored query by name – part of me thinks I must be missing a simpler solution, however if anyone else is encountering the same issue I hope that the following code snippet will be of use.

Required namespaces:

  • Microsoft.TeamFoundation.Client
  • Microsoft.TeamFoundation.WorkItemTracking.Client

/// <summary>
/// <para>Find the TFS QueryDefinition for a specified Team Project</para>
/// <para>Note that if multiple queries match the requested queryName
/// only the first will be used</para>
/// </summary>
/// <param name=”tfsUrl”>URL to the TFS project, including the
/// collection name (Eg, http://tfsserver:8080/tfs/DefaultCollection)</param>

/// <param name=”projectName”>Name of TFS Team Project</param>
/// <param name=”queryName”>Name of Stored Query. Note if multiple
/// exist the first found will be used</param>

/// <returns></returns>
public static QueryDefinition FindQueryItem(string tfsUrl, string projectName, string queryName)
{

// Setup the connection to TFS
TfsTeamProjectCollectionprojectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(tfsUrl));

WorkItemStore workItemStore = projectCollection.GetService<WorkItemStore>();

Project project = workItemStore.Projects[projectName];

return FindQueryItem(queryName, project.QueryHierarchy);

}

///<summary>
/// Recursively find the QueryDefinition based on the requested queryName.
///<para>Note that if multiple queries match the requested queryName
/// only the first will be used</para>
///</summary>
///<param name=”queryName”>Name of Stored Query. Note if multiple exist
/// the first found will be used</param>

///<param name=”currentNode”>Pointer to the current node in the recursive search</param>
///<returns>QueryDefinition</returns>
private static QueryDefinition FindQueryItem(string queryName, QueryItem currentNode)

{

// Attempt to cast to a QueryDefinition
QueryDefinitionqueryDefinition = currentNode as QueryDefinition;

// Check if we’ve found a match
if
(queryDefinition != null && queryDefinition.Name == queryName)

return queryDefinition;

// Attempt to cast the current node to a QueryFolder
QueryFolder
queryFolder = currentNode as QueryFolder;

// All further checks are for child nodes so if this is not an
// instance of QueryFolder then no further processing is required.

if
(queryFolder == null)

return null;

// Loop through all the child query item
foreach (QueryItem qi in queryFolder)
{

// Recursively call FindQueryItem
QueryDefinition
ret = FindQueryItem(queryName, qi);

// If a match is found no further checks are required
if
(ret != null)

return ret;

}

return null;

}

Advertisements

BizTalk 2006 and Versioning GAC’d Dependencies

Overview

Recently I found myself working on a BizTalk 2006 project that had been pre-configured to use a number of referenced assemblies that ultimately would be deployed to the GAC on the target BizTalk machine. Unfortunately I found that managing the versions and deployments of this configuration to be ‘problematic’ at best, so I’ve been giving some thought to how this might be done differently.

My basic requirements for this process are as follows:

  • The process must allow for assemblies built in a separate solution
  • The process must be easy for developers
  • All environments (including developers machines) must be installed the same way
  • Deployed assemblies must be versioned

This post describes how I went about achieving these goals – though I’m sure there must be other ways to do this as well.

Setting up the new Development / Deployment Process

Step 1 – Create a new Setup project

Create a new Visual Studio Installer project within your solution, and configure the following properties (along with any others you may feel you want to change).

Property Value
RemovePreviousVersions True
Version 1.0.0 (then increment for each build)

The real key for me here is the RemovePreviousVersions option. If this is set to “False” then the developers will need to manually uninstall the previous package – regardless of whether they are installing an upgrade.

By setting this to “True”, we are encouraging the development team to remember to increment the version of the setup package every upgrade. Changing the version of the setup package at this stage may also prompt the developer to increment the assembly version as well.

Step 2 – Add all project output to the GAC

In the “File System” setup, add a new target folder for the Global Assembly Cache. This is done by simply right-clicking on “File System on Target Machine”, then selecting “Add Special Folder”, then “Global Assembly Cache Folder”.

Now that the GAC folder is included in the installation folders list, add the “Primary Output” of your assemblies.

Step 3 – Add all project output to the Application Folder.

Technically this step is not really required – BizTalk only reads the assemblies from the GAC, so why bother putting them in the application folder as well …

There is a reason though – Visual Studio 2005 doesn’t allow you to reference a custom assembly directly from the GAC, so in order to allow the BizTalk Solution references to be upgraded each time a new copy of the assemblies is installed it is much easier to copy the output to the file system as well as the GAC.

Step 4 – Compile the Installation File, and install on your BizTalk environment

Not much to be said about this step really: compile the installation file and install onto the BizTalk development environment. I found I was doing this step fairly frequently through the day as incremental changes to the assemblies were made – so it pays to keep a network share to the installation folder open if possible.

Note that if the developer forgets to increment the version number of the installation package the installation will be blocked at this point. This is the desired result, as we always want the version incremented!

Step 5 – Add assembly references to your BizTalk solution

Open your BizTalk solution and add references to the new assemblies directly from the application installation folder (typically c:\program files\your company\your product).

Step 6 – Deploy to TEST and PROD environments the same way

Now that we have a consistent package for the assemblies don’t forget to maintain that consistency across all deployment environments … not just your dev box!

Resulting Development Process

After the changes above have been implemented, the development process for on-going changes.

Other Approaches?

I’d be quite keen to hear about how others have approached this problem. I’m unsure what is considered a pragmatic best practice in this space – and I can already hear the developers shouting about the extra steps introduced here! Is there a better way to do this while still meeting the requirements listed at the top of this post?

Debugging .NET IL at Runtime using Reflector / Deblector

The other day we encountered a problem with some inconsistent processing within the POP adapter for BizTalk. If the adapter was processing an email with a very specific set of attachments, the adapter failed to hand the message out to the BizTalk engine, and all following messages on the receive adapter became blocked. Anecdotally we believed this was related to the S/MIME decoder being used by the adapter, but we were struggling with what specific characteristics of the attachments required to reproduce the issue.

Let me make this clear from the start … we didn’t actually manage to resolve this issue using this technique. Having said that I did find the whole process of debugging IL for runtime code very interesting and wanted to share the basics for getting started.

Step 1: Install the components

The tools we used for this are both available for free download. These will need to be copied onto the machine where the .NET process you wish to debug is located.

Installing reflector is just a matter of extracting the runtime files onto your machine. The Add-in can be installed by extracting the files to a subdirectory under the Reflector application path, then adding the Add-in into Reflector (Menu -> View -> Add-in’s).

Deblector can then be activated within Reflector from the Tools menu.

Step 2: Attach to the BizTalk process

The next step is to load the required assemblies into Reflector. In my case this was the Microsoft.BizTalk.Pipeline.Components.dll file that comes with BizTalk Server 2006.

Note that at this stage it pays to navigate through the methods you are likely to be debugging, to ensure that all the dependant assemblies are also included. Reflector will prompt you to load any decencies that are identified for the methods you are reading. This is also a good chance to learn a bit about how the application hangs together, and where logical debugging breakpoints should be applied.

Once the assemblies have been loaded we need to attach Deblector to the process to be debugged. In my case this was the BTSNTSvc.exe process.

Note: For BizTalk this got a bit complicated as there are a number of instances of this process running, so some trial and error was required to find the right one. I also found that stopping all the host instances in BizTalk Administration Console except for the one containing the pipeline you wish to debug was helpful to help filter the list.

Note that the debugger is automatically in pause mode when you attach to the process.

Step 3: Set your breakpoints, and Debug!

Using the explorer included in Reflector, navigate to the method to be debugged (in my case, MIME_SMIME_Decoder.Execute2).

Examine the IL view, and identify a line that you recognise. Reading IL can be a bit daunting, and I’m definitely not proficient with this as a language. I’ve found that searching for strings used for writing log files

Setting up the breakpoint had me a bit confused to begin with, as I could see the breakpoint button but it was not obvious as to how to select the line to apply the breakpoint to. In the end it’s as simple as selecting the line in the IL View tab and clicking the breakpoint icon. Alternatively you can use the Command textbox and the break command (b [location]). I found this useful when wanting to re-setup a number of breakpoints after restarting the BizTalk process and reattaching the debugger.

At this stage you also want to consider whether you want the debugger to break if an exception is thrown. This can be toggled using one of the icons on the toolbox.

Once you have all the breakpoints setup and ready to go, click the Play icon to let the attached process continue until the next breakpoint.

Now it’s debugging as normal – except the commands being stepped through take a bit more effort to comprehend. As a final note, I did notice that the highlighted line is often indicating the instruction prior to the one being executed so if you want to step into a specific function call then you need to do so a couple of instructions before the function is called.