But it works on my PC!

The random thoughts of Richard Fennell on technology and software development

More on running multiple TFS build controllers on a single VM

I have been having a on-going project to run multiple build controllers on a single VM. Today I needed to reconfigure a on of the controllers to point at a different TPC. You have to do this the correct way to avoid problems.

My error log was full of

Http communication failure:
Exception Message: Cannot listen on pipe name 'net.pipe://build/ServiceHost/1' because another pipe endpoint is already listening on that name. (type AddressAlreadyInUseException)

It all boiled down to the fact I ended up with two controllers trying to use the same URI, in my case


The number at the end of this URI is assigned when the controller is registered with a TPC. If, as I did, you just stop a controller and edit its properties to point at another TPC and restart it, it is possible to end up with two controllers on the same box trying to use the same ID.

The simple fix is to unregister the build controller and the register it with the new TPC as needed. This will cause the machine to be scanned and new, empty ID chosen for the URI. As as detailed in Jim Lamb’s original post.

As a side effect I also saw errors in the log saying custom activity assemblies could not be loaded due to permission errors. This all turned out to be that the custom activities are stored in

C:\Users\[tfs build account]\AppData\Local\Temp\BuildAgent\[agent ID] 

So if two agents have on the ID, even if one’s parent controller is failing to load fully, it will tend to lock the files for the other controller. Again this was fixed by registering the controller and agents in the correct manner

WP7 update fails when using laptop docking station, works when direct to laptop

When I plugged my WP7 LG-E900 today it told me there was a update. When I tried to install this it failed, twice. So I changed USB cable and plugged it directly into a port on my laptop, not my usually phone syncing cable plugged into my laptops docking station, and it worked.

So not sure if it a USB cable quality issue, or a USB port issue, just something to remember.

Solution to ‘Missing requirement: Shared profile’ error when installation TEE SP1 on Eclipse Indigo

[Updated 1 mar 2012 - This should only effect you if Eclipse is unzipped into your 'c:\program files' folder structure)

During my new laptop build I have had to reinstall Eclipse, so I took the chance to upgrade to the Indigo release. When I tried to install the TFS 2010 Team Explorer Everywhere SP1 plug-in I got the error

Cannot complete the install because one or more required items could not be found.
  Software currently installed: Shared profile (SharedProfile_epp.package.java
  Missing requirement: Shared profile (SharedProfile_epp.package.java requires 'org.maven.ide.eclipse []' but it could not be found

This stumped me for a while, but after a bit of searching on Eclipse forums I found this was a problem common to installing other plug-ins, not just TEE, so not a TEE dependency as the error suggests.

The issue was you have to be running Eclipse as an administrator to install the plug-in. Judging from the forums this has tripped a few people up with plug-ins on the Indigo release, seems this was not the case with the previous releases such as Helios.

Once you have installed the plug-in as administrator you can restart Eclipse in standard mode and connect to your TFS server as you would expect.

Moving a VHD boot disk to Hyper-V

I have just replaced my old Acer laptop with a rather nice Lenovo W520. This has plenty of memory and is able to run Hyper-V. In the past for TFS demos I had used boot from VHD to boot the Acer into Windows 2K8, as the Acer could not run Hyper-V due to lack of hardware virtualisation support in the bios. So I had a fully configured VHD boot what I wanted to move to Hyper-V.

My first though was I could just use the P2V system build into SCVMM. I ran the wizard, connected to my VHD booted Acer laptop, provide the details asked for and all looked good until the last screen when I got the error

Error (13256):
The disk with index 1 on source machine is an attached virtual hard disk. This configuration is not supported for physical-to-virtual conversions.


So that was a non starter.

So I just copied the VHD to my new Hyper-V server and created a new Hyper-V VM using it. However, when I tried to boot this it said I had no boot sector. When you think about it this not unreasonable as this VHD was always booted off my laptops primary disk boot partition. The process to fix this was as follows (thanks to Rik for some help here)

  1. Mount the VHD directly onto my Windows 2K8 Hyper-V host via the Disk Manager in the admin tools.Don’t bother to assign a drive letter.
  2. Select the Windows 2K8 partition on the VHD and shrink it by 110Mb, this is to create space for the boot partition (I suppose you could use a VHD resizer tool, but that would be slower from my experience as this rewrites the whole VHD, the shrink is very quick)
  3. In the new gap, create a simple partition and format as NTFS with the same ‘System Reserved’
  4. Dismount the VHD
  5. Start the Hyper-V VM using the edit VHD, you will still get the no boot device error
  6. Attach a Windows 7 DVD ISO and restart the VM, it should boot into the Windows setup. On the first screen press Shift F10 to get the command prompt.
  7. You should be on drive X: and see a drive C; (your old VHD partition) and D: ( the newly created one)
  8. Run the command bcdboot c:\windows /s d: to create the boot partition
  9. Load diskpart and (probably) the following commands
    • select the VHD disk – sel disk 0
    • list the partitions – list part
    • select the new partition – sel part 2
    • make it active – active
    • exit distpart
  10. As a check you can run the command bcdedit to see that it added something (this command would have returned nothing prior to bcdboot being run)

You should now be able to restart the VM and it should boot using the installed Windows 2K8 partition. As it has changed hardware it will probably want to reboot a few times as drivers are updated.

Workaround to connect to a TFS Lab Environment from outside a TMG firewall

Whist on the road I have had need to access our Lab Management system via our TMG firewall through which we expose our TFS 2010 for remote users (via SSL). When I load Microsoft Tests Manager (MTM) I can connect to the TFS server, as expected, and go into ‘Lab Center’ mode. I can see my project’s environment and can start, stop and deploy them without issue (all communication routed via our TFS server). However the MTM environment viewer fails to make a connection to the test VMs in the environments.


MTM environment viewer can connect to an environment in two ways:

  • Host connection – via the Hyper-V management protocols
  • Guest connection – via a RDP session to the VM’s operating system

From outside our firewall a host connection is not an option as the required ports are not open. So my only option was a guest connection. However, our TMG firewall is set to provide a  RD gateway, effectively a proxy for RDP sessions. You have to configure RDP to use this, and have to authenticate with this gateway prior to authenticating with the actual target remote machine.


The problem is MTM does not support the use of TMG RD Gateways.

However there is a solution. If I right click on the VM in MTM Environment Viewer you can launch a standard remote desktop session.


If you do this you will be prompted to authenticate correctly.Firstly with your domain account to authenticate with the TMG RD gateway, then for other credentials to the test VM.

So a reasonable workaround, if a VPN or TMG Direct Access is not on option for you.

TF30162: Task "BuildTask" from Group "Build" failed – when creating a team project

When trying to create a new Team Project on my test TFS 2010 basic installation I got the error

Time: 2011-07-05T11:43:36
Module: Engine
Event Description: TF30162: Task "BuildTask" from Group "Build" failed
Exception Type: Microsoft.TeamFoundation.Client.PcwException
Exception Message: Multiple identities found matching workspace name 'TYPHOONfbb296e15246421e9fc8d25e9d128512typhoon (VC)' and owner name 'BLACKMARBLE\fez'. Please specify one of the following workspace specs:
TYPHOONfbb296e15246421e9fc8d25e9d128512typhoon (VC);BLACKMARBLE\fez
TYPHOONfbb296e15246421e9fc8d25e9d128512typhoon (VC);BLACKMARBLE\fez
Stack Trace:
   at Microsoft.VisualStudio.TeamFoundation.Build.ProjectComponentCreator.ExecuteInternal(ProjectCreationContext context, XmlNode taskXml, Boolean validationOnly)
   at Microsoft.VisualStudio.TeamFoundation.Build.ProjectComponentCreator.Execute(ProjectCreationContext context, XmlNode taskXml)
   at Microsoft.VisualStudio.TeamFoundation.ProjectCreationEngine.TaskExecutor.PerformTask(IProjectComponentCreator componentCreator, ProjectCreationContext context, XmlNode taskXml)
   at Microsoft.VisualStudio.TeamFoundation.ProjectCreationEngine.RunTask(Object taskObj)
--   Inner Exception   --
Exception Message: Multiple identities found matching workspace name 'TYPHOONfbb296e15246421e9fc8d25e9d128512typhoon (VC)' and owner name 'BLACKMARBLE\fez'. Please specify one of the following workspace specs:
TYPHOONfbb296e15246421e9fc8d25e9d128512typhoon (VC);BLACKMARBLE\fez
TYPHOONfbb296e15246421e9fc8d25e9d128512typhoon (VC);BLACKMARBLE\fez (type MultipleWorkspacesFoundException)

Exception Stack Trace:    at Microsoft.TeamFoundation.VersionControl.Client.InternalCache.GetWorkspace(Guid repositoryGuid, String name, String owner)
   at Microsoft.TeamFoundation.VersionControl.Client.InternalCache.Merge(XmlNode xmlOnDisk, InternalWorkspaceConflictInfo[]& removedConflictingWorkspaces)
   at Microsoft.TeamFoundation.VersionControl.Client.InternalCache.Save(XmlNode inputXml, XmlNode outputXml, InternalWorkspaceConflictInfo[]& removedConflictingWorkspaces)
   at Microsoft.TeamFoundation.VersionControl.Client.InternalCacheLoader.SaveConfigIfDirty(InternalCache internalCache, InternalWorkspaceConflictInfo[]& conflictingWorkspaces)
   at Microsoft.TeamFoundation.VersionControl.Client.Workstation.UpdateWorkspaceInfoCache(String key, VersionControlServer sourceControl, String ownerName)
   at Microsoft.TeamFoundation.VersionControl.Client.Workstation.EnsureUpdateWorkspaceInfoCache(VersionControlServer sourceControl, String ownerName, TimeSpan maxAge)
   at Microsoft.TeamFoundation.Build.Controls.VersionControlHelper.CheckinFiles(VersionControlServer versionControl, Dictionary`2 localPathsToServerPaths, String checkinComment)
   at Microsoft.VisualStudio.TeamFoundation.Build.ProjectComponentCreator.CheckinFiles(ProjectCreationContext context, VersionControlServer versionControl, List`1 templates)
   at Microsoft.VisualStudio.TeamFoundation.Build.ProjectComponentCreator.ExecuteInternal(ProjectCreationContext context, XmlNode taskXml, Boolean validationOnly)

This turns out to be another version of the local cache refresh issue I blogged about recently. The issue was I had deleted a couple of team projects on my TFS server via the TFS Administration Console, but my local VS2010 copy did not know as the cache had not been refreshed. Unloading VS2010, reloading it so the local cache was refreshed and then the create new project works fine

Cannot connect to a Lab Management Environment using the MTM Environment Viewer

Today we had a problem that we could not connect to VMs within a Lab Management environment from the Environment Viewer in MTM. We had composed the environment from VMs independently create and tested on the HyperV host. The plan in the end is to have this as a network isolated environment, but for now it is a private domain that exists on our main LAN.

The first issue we had was that as this was a private domain the various hosts were not registered on our DNS, so we got a DNS lookup error for the VM host names. This is best fixed with network isolation, but for a quick fix we put some entries in a local hosts file on the PC we were using to resolve the name to IP addresses.

The next problem was one of concepts. The environment had been composed by one user (and could access everything via a host connection via Hyper-V, with no local host file fixes), but it was to be used by another user, a tester who was not the owner of the environment (yes again I know we should they should be provisioning their own network isolated version). This mean that a Hyper-V based host connection was not possible, as you have to be the owner to get a host connection.

This meant that the new user had to use a guest connection, a Remote Desktop Connection (RDC) created behind the scenes by the MTM Environment Viewer. This worked for the domain controller (a server OS) but failed for the other three VMs in the environment which were all running Windows 7 with a ‘lost connection to virtual machine error’


Turns out the issue was the level of security set for RDC connection in Windows 7. We remoted onto the VMs with the problems using the standard Windows RDC client (not MTM) and set the Allows connections from computers running any version of RD.


Once this was done the Environment Viewer could make guest connections and all was good in the world.

How to fix extra Quickstart help menu items when installing Typemock Isolator

I recently noticed that I had a few too many ‘Typemock Isolator Quickstart’ help menu items in Visual Studio 2010


After a quick check with Typemock it seems this was a known issue with previous versions of Isolator, you should not see it on a new installation (6.0.10). If you do have the problem do as I was advised, run the VS macro, created by Travis Illig, to remove the extra items.

Cross domain usage of TFS Integration Platform

Whist trying to do a cross domain migration of some source between two TFS2010 servers, I got the less than helpful runtime exception

System.ArgumentNullException: Value cannot be null.
Parameter name: activeWorkspace
at Microsoft.TeamFoundation.Migration.Tfs2010VCAdapter.TfsUtil.CleanWorkspace(Workspace activeWorkspace)
at Microsoft.TeamFoundation.Migration.Tfs2010VCAdapter.TfsVCMigrationProvider.ProcessChangeGroup(ChangeGroup group)

On checking the _tfsintegrationservice_<timestamp>.log I found the more useful

TFS::Authenticate : Caught exception : Microsoft.TeamFoundation.TeamFoundationServerUnauthorizedException: TF30063: You are not authorized to access tfsserver.otherdomain.com. ---> System.Net.WebException: The remote server returned an error: (401) Unauthorized.

The issue is that when you setup the migration you are prompted for credentials for the remote server, but the actual migration does no occur in the same thread as you setup the definitions, so it only has its local credentials and none for the remote system. Hence the 401 error.

There is no way to enter two sets of credentials within the Integration tool itself, but there is a workaround on Willy’s Cave. This is to place the remote credentials in the PC’s credential manager, this work fine for me

Creating a TFS Team Project Collection using Powershell

Grant Holiday posted on how to create a TPC using Powershell. However his post did not address how to set the SharePoint or Reporting Services parameters. His example used for the form

Dictionary<string, string> servicingTokens = new Dictionary<string, string>();
servicingTokens.Add("SharePointAction", "None"); // don't configure sharepoint
servicingTokens.Add("ReportingAction", "None"); // don't configure reporting services

So not much use if like ourselves you have your TFS integrated with the company wide SharePoint farm

Finding the Parameters (the hard way)

If you want configure SharePoint or Reporting Services it turns out there is not source of documentation for the process. So thanks then to Chris Sidi for telling me how to find out the required options. This is his process to find out what parameters a TPC needs to be created with:

  1. Create a TPC via the TFS Administration Console, specifying a custom configuration for Sharepoint and Reporting for your system.
  2. In the Administration Console at the bottom of the screen, switch to the Status tab. Double-click “Create Collection” to load the servicing log.
  3. In the first ~15 lines of the servicing log, find the JobId (e.g. “Setting token. Key: JobId. Value: 9638bd57-f494-4ac3-a073-dd1548ab24dc.”)
  4. Using Powershell, query the servicing tokens used:

[Reflection.Assembly]::Load("Microsoft.TeamFoundation.Client, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
$credProvider = new-object Microsoft.TeamFoundation.Client.UICredentialsProvider
#Update the TFS url as necessary
$tfsConnection = new-object Microsoft.TeamFoundation.Client.TfsConfigurationServer "
http://localhost:8080/tfs", $credProvider
$jobService = $tfsConnection.GetService([Microsoft.TeamFoundation.Framework.Client.ITeamFoundationJobService])

# Replace the JobId. Use the one in the servicing log.
$jobId = '9638bd57-f494-4ac3-a073-dd1548ab24dc'
$servicingJob = $jobService.QueryJobs([Guid[]] @($jobId))[0]

This script gets the list of parameters as shown below which we can pass into the PowerShell script used to create a new  TPC.

SharePointAction UseExistingSite
SharePointServer 3eYRYkJOok6GHrKam0AcSA==wytV0xS6vE2uow3gjrzAEg==
SharePointSitePath sites/test
ReportingAction CreateFolder
ReportServer 3eYRYkJOok6GHrKam0AcSA==KRCi2RTWBk6Cl1wAphaxWA==
ReportFolder /TfsReports/test

It is shame the SharePoint and Reporting Services servers are returned as hash codes not their URLs, but as these will probably be fixed for any TFS implementation this is not a major issue as they can just be hardcoded.

Finding the Parameters (the easy way)

Once I ran this script I actually noticed that I already had access to this information without running  PowerShell or creating any trial TPCs. Isn’t that so often the case the information is under your nose but you don’t recognise it.

Actually all the parameters are actually shown at the start of the creation log for any TPC creation on a given TFS server. Just look for the log files via the TFS admin console.

[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational] Creating dictionary with 14 initial tokens:
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     FinalHostState => Started
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     VMM_SHARES (Value is an empty string.)
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     VMM_HOSTS (Value is an empty string.)
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     INT_USRACC (Value is an empty string.)
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     SharePointAction => UseExistingSite
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     SharePointServer => 3eYRYkJOok6GHrKam0AcSA==wytV0xS6vE2uow3gjrzAEg==
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     SharePointSitePath => sites/test
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     ReportingAction => CreateFolder
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     ReportServer => 3eYRYkJOok6GHrKam0AcSA==KRCi2RTWBk6Cl1wAphaxWA==
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     ReportFolder => /TfsReports/test
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     DataTierConnectionString => Data Source=sqlserver;Initial Catalog=Tfs_Configuration;Integrated Security=True
[Info   @11:12:34.876] [2011-05-04 20:32:36Z][Informational]     CollectionName => test
[Info   @11:12:34.876] [2011-05-04 20:32:37Z][Informational]     InstanceId => 0cf30e1d-d8a6-4265-a854-9f6c5d288f7e
[Info   @11:12:34.876] [2011-05-04 20:32:37Z][Informational]     DefaultDatabase => Data Source=sqlserver;Initial Catalog=Tfs_test;Integrated Security=True

The revised TPC creation script

So given this new set of parameters we can edit Grant’s script to pass in all the extra parameters as shown below

    [string]$tpcName = $( throw "Missing: parameter tpcname"),
    [string]$serverUrl = http://localhost:8080/tfs/ ,
    [string]$sqlServer = "sqlserver" ,
    [string]$spBase = "sites", 
    [string]$spServer = "3eYRYkJOok6GHrKam0AcSA==wytV0xS6vE2uow3gjrzAEg==", 
    [string]$rsBase = "TfsReports",
    [string]$rsServer = "3eYRYkJOok6GHrKam0AcSA==KRCi2RTWBk6Cl1wAphaxWA==" )

Write-Host "Using the TPC with the following settings"
Write-Host "tpcName:   $tpcName"
Write-Host "serverUrl: $serverUrl"
Write-Host "sqlServer: $sqlServer"
Write-Host "spBase:    $spBase"
Write-Host "spServer:  $spServer"
Write-Host "rsBase:    $rsBase"
Write-Host "rsServer:  $rsServer"

# Load client OM assembly.
[Reflection.Assembly]::Load("Microsoft.TeamFoundation.Client, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");

# Get the server
$tfsServer = new-object Microsoft.TeamFoundation.Client.TfsConfigurationServer $serverUrl;

# Create the token set
$servicingTokens = New-Object "System.Collections.Generic.Dictionary``2[System.String,System.String]"

$spPath = $spBase +"/" +  $tpcName;
Write-Host "Sharepoint path is  $spPath"
$servicingTokens.Add("SharePointAction", "UseExistingSite");
$servicingTokens.Add("SharePointServer", $spServer);
$servicingTokens.Add("SharePointSitePath", $spPath);

$rsPath = "/" + $rsBase + "/" + $tpcName
Write-Host "Reporting Services path is  $rsPath"
$servicingTokens.Add("ReportingAction", "CreateFolder");
$servicingTokens.Add("ReportServer", $rsServer);
$servicingTokens.Add("ReportFolder", $rsPath);

# Create and run the job
$tpcSvc = $tfsServer.GetService([Microsoft.TeamFoundation.Framework.Client.ITeamProjectCollectionService]);

$sqlString ="Server=$sqlServer;Integrated Security=SSPI;"
Write-Host "SQL connection string is  $sqlString "

$job = $tpcSvc.QueueCreateCollection(
    $tpcName,      # collection name.
    "",                  # description.
    $false,              # don't make this the default collection.
    "~/" + $tpcName + "/",   # virtual directory.
    "Started",           # State after creation.
    $servicingTokens,               # tokens for other services.
    $sqlString,       # The SQL instance to create the collection on. Specify SERVER\INSTANCE if not using default instance
    $null,               # null because the collection database doesn't already exist.
    $null)               # null because the collection database doesn't already exist.

Write-Host "Creating TPC (this could take a few minutes)"
$collection = $tpcSvc.WaitForCollectionServicingToComplete($job)
Write-Host "Compeleted"

If you get any errors from the script the best place to go is the TFS Admin console to look at the logs (the same ones you used to find the parameters). You should see the detailed create process log that gives normal TF errors as to why the process has failed; usually rights on SharePoint for Reporting Services from my experience.