Multiple TFS Build Controllers per Team Project Collection

This builds upon my previous post to mix domain and non-domain build servers together.  I wanted to have a controller each to manage the various build agents within the domain and non-domain build servers.  Enabling this was a piece of cake.

Head over to your TFS Admin Console on your Build Server, and create a new controller.


Reassign each agent to use the new controller by clicking on the Properties link, then update the Controller value.


Skip over to queue a new build.  You’ll notice that now you have 2 build controllers to select from.  Target the new BC and you’re done!


Non-Domain TFS Build Server with Domain TFS

With some spare time on hand, I wanted to explore if there we were to mix domain-joined build servers with non domain-joined ones, since this could open up a couple of interesting possibilities.

1. Ensure that the target TFS server is reachable, so that we can put proxy and firewall issues aside.

2. Install TFS, but select to only configure Team Foundation Build ServiceTFSBuildServiceOnly

2. Define the TFS Server, then select the Team Project Collection


3. Enter the credentials that your build service will run as.  Ensure that the necessary permissions have been granted, otherwise you’ll get a TF254021 surprise.


4. Continue with the installation, and you’re done!


5. So now you have a non-domain build service (with 2 agents) connected to a domain-joined TFS and Build Controller.





#To set the permissions, make sure that your TFS target is not a Domain Controller.  Create a local account (e.g. remotebuild) on TFS, your build controller and your Non-Domain Build Server. Make sure they have the same password. I also added the account to the Project Collection Build Service.

# Make sure that communication on port 9191 from Build Controller to your Build Agent is enabled.

TF30063: You are not authorized…!

But first, some background.  My connection to TFS is via HTTPS, using an internal CA signed SSL Cert.


HTTP works fine(using FQDN), but with custom domain names and HTTPS, sometimes it works, sometime it doesn’t.

When I connect to the HTTPS url via IE, the connection works, but no lock ICON appears.  If I repeat the same action inside the VS2013 browser (Ctrl-W, W), a revocation failure dialog sometimes pop up.  Regardless of selection, the authentication still fails.


I’ve tried the clear cookie method suggested, disabling cert revocation checks on the server (via netsh) and locally (via gpedit), or at least I think I did, but no luck yet.

This is irritating… Gah!

[Edit] Checked permissions as described here but still no go …

[Edit] Checked that server had a 3+ min delay compared to client, fixed that, cleared cache etc, but still no go…

[Edit] Seems to be no correlation between IE having a lock sign, and the revocation message inside VS browser.

Customising VS2010 project files.

Just a quick snippet for doing the following (mainly for myself):

  • Performing actions conditionally as part of a build process
  • List of available variables
  • Invoking the TransformXml Tasks
  • Invoking the Copy Tasks
Code Snippet
  1. <Target Name="AfterBuild" >    
  2.     <CallTarget Condition="$(IsTFSPackagingBuild)=='True'" Targets="TFSBuild" />
  3.     <CallTarget Condition="$(IsTFSPackagingBuild)!='True'" Targets="LocalBuild" />
  4.   </Target>
  5.   <Target Name="TFSBuild" >
  6.     <ItemGroup>
  7.       <DeleteAfterBuild Include="$(WebProjectOutputDir)\Web.*.config" />
  8.     </ItemGroup>
  9.     <TransformXml Source="Web.config" Transform="Web.TEST.config" Destination="$(WebProjectOutputDir)\Web.TEST.config.transform" />
  10.     <TransformXml Source="Web.config" Transform="Web.QA.config" Destination="$(WebProjectOutputDir)\Web.QA.config.transform" />
  11.     <TransformXml Source="Web.config" Transform="Web.PROD.config" Destination="$(WebProjectOutputDir)\Web.PROD.config.transform" />
  12.     <Delete Files="@(DeleteAfterBuild)" />
  13.   </Target>
  14.   <ItemGroup>
  15.     <MySourceFiles Include="Web.config.transform" />
  16.     <MyDestinationFiles Include="Web.config" />
  17.   </ItemGroup>
  18.   <Target Name="LocalBuild" >  
  19.     <Message Text="MSBuild: $(MSBuild)"/>
  20.     <Message Text="MSBuildBinPath: $(MSBuildBinPath)"/>
  21.     <Message Text="MSBuildExtensionsPath: $(MSBuildExtensionsPath)"/>
  22.     <Message Text="MSBuildExtensionsPath32: $(MSBuildExtensionsPath32)"/>
  23.     <Message Text="MSBuildExtensionsPath64: $(MSBuildExtensionsPath64)"/>
  24.     <Message Text="MSBuildLastTaskResult: $(MSBuildLastTaskResult)"/>
  25.     <Message Text="MSBuildNodeCount: $(MSBuildNodeCount)"/>
  26.     <Message Text="MSBuildOverrideTasksPath: $(MSBuildOverrideTasksPath)"/>
  27.     <Message Text="MSBuildProgramFiles32: $(MSBuildProgramFiles32)"/>
  28.     <Message Text="MSBuildProjectDefaultTargets: $(MSBuildProjectDefaultTargets)"/>
  29.     <Message Text="MSBuildProjectDirectory: $(MSBuildProjectDirectory)"/>
  30.     <Message Text="MSBuildProjectDirectoryNoRoot: $(MSBuildProjectDirectoryNoRoot)"/>
  31.     <Message Text="MSBuildProjectExtension: $(MSBuildProjectExtension)"/>
  32.     <Message Text="MSBuildProjectFile: $(MSBuildProjectFile)"/>
  33.     <Message Text="MSBuildProjectFullPath: $(MSBuildProjectFullPath)"/>
  34.     <Message Text="MSBuildProjectName: $(MSBuildProjectName)"/>
  35.     <Message Text="MSBuildStartupDirectory: $(MSBuildStartupDirectory)"/>
  36.     <Message Text="MSBuildThisFile: $(MSBuildThisFile)"/>
  37.     <Message Text="MSBuildThisFileDirectory: $(MSBuildThisFileDirectory)"/>
  38.     <Message Text="MSBuildThisFileDirectoryNoRoot: $(MSBuildThisFileDirectoryNoRoot)"/>
  39.     <Message Text="MSBuildThisFileExtension: $(MSBuildThisFileExtension)"/>
  40.     <Message Text="MSBuildThisFileFullPath: $(MSBuildThisFileFullPath)"/>
  41.     <Message Text="MSBuildThisFileName: $(MSBuildThisFileName)"/>
  42.     <Message Text="MSBuildToolsPath: $(MSBuildToolsPath)"/>
  43.     <Message Text="MSBuildToolsVersion: $(MSBuildToolsVersion)"/>    
  44.     <Copy
  45.             SourceFiles="@(MySourceFiles)"
  46.             DestinationFiles="@(MyDestinationFiles)"
  47.         />
  48.   </Target>

Additionally, links to the resources that dive into the details.

Hope this helps!


My HTC ONE X arrived today, with a free HD media link to be redeemed in a couple of weeks.

I guess I will root and reflash my N1 at some point

Migrating WF Application to Azure via Windows Azure Accelerator for Web Roles

While wrapping up my demos for my presentation “Moving WF applications to Azure”, I decided to repackage my demos using Windows Azure Accelerator to conserve the number of Web Roles I was using in Azure. 

A quick summary of the issue is as follows:

  1. Create a Windows Azure Accelerator project, and upload it to Azure (Steps performed according to instructions provided by WAA)
  2. From the base address (i.e. <application>, create a IIS Site name.  I just typed a random, non-active hostname for the Hostname, as I was intending to use the test link instead.
  3. Create a Windows WF 4.0 project, and browse to it. The generated screen with a link to the WSDL is displayed.image
  4. Publish the WF Application to the IIS web site.  It doesn’t matter if the deployment is marked as an IIS application.image
  5. Browse to the test site where a page showing that metadata publishing is disabled. (i.e the /test/testwf/ location, rather than from the host name)image
  6. No amount of web.config changes will enable the metadata publishing, such as an example below.image

Logging onto the Azure Web Role instance revealed the following IIS setup.


I’m guessing that the test sites use URL Rewrite, but somehow the web.config is not picked up.

What finally worked for me is as follows:

  1. Get a DNS Alias (CNAME) to point to my base cloud application, e.g. using a free domain name from
  2. Reconfigure WAA to accept the new Host Nameimage
  3. Browse to the WF Service using the Site address instead of the test site address, and voila, the no configuration setup now works.
  4. image

I hope this helps someone save a couple of hours of sleep.  Now onto figuring out Azure Composite Applications.

Presentation: "Moving WF Applications to Azure”


My presentation "Moving WF Applications to Azure" to the Azure User Group Singapore ( on 29th Nov 2011 covered the following topics:
– What is Window Workflow Foundation?
– What are the features, and how does one implement them?
– Why is it relevant to applications moving into Azure?
– What are my migration / development options for using WF in Azure?


Slides have been uploaded to Slideshare:

Demo codes have been uploaded to Azure Storage
– WFSoln:
– AzureWFSoln:

[Updated] Migrations using Windows Azure Accelerator for Web Roles has been resolved.  Please take a look at