Posts Tagged ‘TFS’

How to Solve Issues Managing Users on Projects after Upgrade to TFS 2012

September 12th, 2012 No comments

This past weekend we upgraded our server to TFS 2012. After we finished the upgrade, I noticed that I was getting errors while trying to manage permissions on a few of our projects. This is odd because my user account is a TFS Admin, there shouldn’t be anything that I’m not allowed to do and I hadn’t heard of any large security changes that were delivered in 2012.


After some investigation I found that the only projects I was having issues managing were the projects that existed since the early days of our server. Our server has existed since 2009 and this makes it’s second major version upgrade of TFS. As with any permissions issue in TFS, you can use TFSSecurity to gather extensive information on the security configuration of almost any object in TFS.

Using that tool, I was able to generate this table:

Project Created in 08 and upgraded to 2010 and now to 2012 (after following the advise of a forum poster about running a TFSSecurity script to add the ManageMembership permissions to this project)
[+] Read [Project ]\Contributors
[+] ManageMembership [Project ]\Contributors
[+] Read [ Project]\Readers
[+] Read [ Project]\Build Services
[+] ManageMembership [Project ]\Build Services
[+] Read [ Project]\Project Administrators
[+] Write [ Project]\Project Administrators
[+] Delete [ Project]\Project Administrators
[+] ManageMembership [Project ]\Project Administrators

Project Created in 2010 and upgraded to 2012

[+] Read [Project]\Builders
[+] Read [Project]\Project Administrators
[+] Write [Project]\Project Administrators
[+] Delete [Project]\Project Administrators
[+] ManageMembership [Project]\Project Administrators
[+] Write [Project]\Build Editors
[+] Delete [Project]\Build Editors
[+] ManageMembership [Project]\Build Editors
[+] Read [Project]\Contributors
[+] Read [Project]\Readers
[+] Read [PC]\Project Collection Valid Users
[+] Read [PC]\Project Collection Service Accounts
[+] Write [PC]\Project Collection Service Accounts
[+] Delete [PC]\Project Collection Service Accounts
[+] ManageMembership [PC]\Project Collection Service Accounts
[+] Read [PC]\Project Collection Administrators
[+] Write [PC]\Project Collection Administrators
[+] Delete [PC]\Project Collection Administrators
[+] ManageMembership [PC]\Project Collection Administrators

Project Created in 2012

[+] Read [Project]\Readers
[+] Read [PC]\Project Collection Build Service Accounts
[+] Read [Project]\Build Administrators
[+] Read [PC]\Project Collection TestService Accounts
[+] Read [Project]\Contributors
[+] Read [Project]\Project Administrators
[+] Write [Project]\Project Administrators
[+] Delete [Project]\Project Administrators
[+] ManageMembership [Project]\Project Administrators
[+] Read [PC]\Project Collection Valid Users
[+] Read [PC]\Project Collection Service Accounts
[+] Write [PC]\Project Collection Service Accounts
[+] Delete [PC]\Project Collection Service Accounts
[+] ManageMembership [PC]\Project Collection Service Accounts
[+] Read [PC]\Project Collection Administrators
[+] Write [PC]\Project Collection Administrators
[+] Delete [PC]\Project Collection Administrators
[+] ManageMembership [PC]\Project Collection Administrators


For all intents and purposes the project created in 2010 and 2012 are identical from a permissions standpoint.  The project created in 2008 however was missing the above key ACL entries.  To be honest, I’m not sure if they were there and the upgrade removed them or if something else happened; however, before the upgrade I was able to edit these projects and after I was not.

As I mentioned previously, the TFSSecurity program is very powerful and not only can it give you security information, it can also set it, irrespective of what the UI will allow you to do.  This is how I fixed my issue:

First:  You need to get the GUID of the project that you need to adjust permissions on.  I do not know of a way to get it from 2012.   The easiest way to do this is to get it from VS2010.  When you open team explorer and have the project in question in your list, right click and select properties.  The GUID will be in the field whos value looks like this:

Once you have the GUID of your project, you need to get the SID of your project collection administrators group.

Now that we have both of those pieces of information, we execute the following command

Piecing this command out looks something like this (full documentation found here)

  • /a+ , Add permission (/a just shows permissions)
  • Identity, This means that w’re modifying something in the Identity security namespace
  • vstfs:///Classification/TeamProject/*GUID*, this is the specific object we’re modifying security on. In this case, a project
  • ManageMembership, This is the specific permission in the security namespace that we’re modifying
  • SID, This is the user were performing the security action on
  • ALLOW, We’re allowing them to perform the action
  • /collection, the specific TFS Project Collection that the action will be run against.

Voila, you should now be able to manage groups on the project again.  I ran the same command twice, to see if it would cause an issue and the command exited without doing anything.  Given that test, I believe it’s safe to say that writing a script to run this against every project in your TFS instance, especially if you have a lot of old projects, would be the better idea then doing them all by hand.

If you’re experiencing an issue similar to this, hopefully this solves your problem!


P.S. You can see my original forum post here.
(This post updated for more explanation of the command and to fix a display problem with my original example)

Categories: Troubleshooting Tags:

Building WiX MSIs in TFS Preview

June 11th, 2012 1 comment

I spent the weekend getting one of our more complicated projects up and building in the hosted build servers of TFS Preview.  The last step was integrating our WiX deployment packages.   I upgraded to 3.6 RC before I started, just in case.

After creating a demo project with a simple WiX project.  This is the build output that I receive.


Ok, that makes sense.  WiX isn’t installed on the hosted build server.  Since we cannot install WiX on the build server, we must upload everything we will need into source control.  There are two main components here:  the WiX binaries and the WiX msbuild targets files.   I have a folder in source called “Build Stuff” where i put everything that I’m going to reference as part of a build.  I created two sub folders, WiXBin and WiXTarget.


I copied all of the files from C:\Program Files (x86)\WiX Toolset v3.6\bin into the WiXBin folder, and all of the target files from  C:\Program Files (x86)\MSBuild\Microsoft\WiX\v3.x into the WiXTarget folder.

Now we have to tell MSBuild where to find our new files.  On the process tab of the build definition, is a setting called “MSBuild Arguments”.  This allows us to pass overrides directly to MSBuild.  In this case, I passed the following (this should be all one line, I wrapped it so you could read it):


/p:WiXTargetsPath=c:\a\src\BuildStuff\WiXTarget\wix.targets; WixTasksPath=c:\a\src\BuildStuff\WiXBin\WiXTasks.dll; WixToolPath=c:\a\src\BuildStuff\WixBin; WixExtDir=c:\a\src\BuildStuff\WixBin


Given that we have more then one MSI project and they reside at different levels in the folder structure, a relative path to these files didn’t seem like it was the best long term solution.  At least for now (no telling it MS will change it), the source directory for a project being built is C:\a\src.

Now that we have MSBuild set up correct to build our WiX project file, let’s run the build again:

If you’ve set up a new build server before, you’ve probably seen this error.  It’s the error basically telling you that the account running the build doesn’t have administrator permissions.  Since we’re running in a hosted environment, this is not something that we can change.  Our only option is to disable ICE validation.

By opening up the WiX project settings, going to Tool Settings, we can set WiX to suppress the ICE validation step.



After that setting get’s checked in, we re-run the build and we see the MSI in our drop location.


ICE validation steps in the build are a nice to have in that they ensure that the MSI is consistent right away; however, those validations can be run by an infrastructure resource using Smoke.exe locally before being deployed into your QA environment.



Categories: Coding Tags: , , ,

TFS History Reporting with Powershell

June 2nd, 2012 1 comment

A client asked us a few years ago if there was a way to generate a TFS report that would give them a breakdown of check-ins and the specific files changed on each day.  The reasoning was that they stored their SSIS reports for their financial system in TFS and their auditors wanted the information for their audit report.  As the TFS guy, I was tasked with coming up with the solution.

I couldn’t figure out a way to use the TFS warehouse to give them all of the information that they were looking for.  I was about to start writing a console app to pull the data from the TFS API when I remembered that the TFS Power Tools come with PowerShell extensions.   These powershell extensions give you the same functionality as the TFS object model, but with the power of the PowerShell piping.

The first output was a simple select changeset items and output to a file.

Get-TfsItemHistory "$/PROJECTNAME" -Recurse -Version "D1/1/10~D12/31/10" | Sort CreationDate | Select ChangeSetId,Committer,Comment,CreationDate |  Format-Table ChangeSetId,CreationDate,Committer,Comment -Auto -Wrap  | out-file "full.txt"

The ItemHistory comamnd pulls back all of the changesets from 1/1 to 12/31 and pipes that to the sort command.  The data is sorted and then piped to a select comamnd which pulls back the 4 fields we care about displaying.  Now that the data has been filtered to those columns, it’s piped to the format-table command to render and then sent to an output file.   The output looks like this:

ChangesetId CreationDate Committer Comment
———– ———— ——— ——-
21719 1/5/2010 10:43:32 AM edwin.frey  I should really put better changeset commands
21722 1/5/2010 10:59:32 AM edwin.frey  Changeset description #2

The second report is a little more complex and was Check-Ins by name and Date.

Get-TfsItemHistory "$/PROJECTSOURCEROOT" -Recurse -Version "D1/1/10~D12/31/10" | Sort CreationDate | Select ChangeSetId,Committer,Comment,@{n='CreationDate';e={$_.CreationDate.ToShortDateString()}} | Group CreationDate | Foreach { "$($_.Name) - Total Checkins: $($_.Count)";$_.Group | group Committer | sort @{e={$_.Count};asc=$false},Name | Format-Table Count,Name -auto } | out-file groupedByDate.txt

Let’s walk through what this script is doing:

Get-TfsItemHistory "$/PROJECTSOURCEROOT" -Recurse -Version "D1/1/10~D12/31/10" | Sort CreationDate 

will invoke the TFS powershell comment and pull back the change set history on that source root, recursively between the first and the last of the year 2010.  The output of the command is then piped into the Sort command to sort the results by Date.

Select ChangeSetId,Committer,Comment,@{n='CreationDate';e={$_.CreationDate.ToShortDateString()}} | Group CreationDate

This command will select the specific fields we care about, format the date,  and then group on the creation date.  We are grouping by the date because we want the CreationDate to be the header of our output.

Foreach { "$($_.Name) - Total Checkins: $($_.Count)";$_.Group | group Committer | sort @{e={$_.Count};asc=$false},Name | Format-Table Count,Name -auto }

The foreach is over the grouped history from the previous group on CreationDate.  Inside of that foreach, we have 4 commands acting on the input.  The first command returns the name of the group, which in this case is the CreationDate, the total check-in count, and the group data.  The group data is then grouped again by the Committer, then piped into a sort command that sorts by count, and then returns the name of the Committer.  The final command is the format command that specifies that the output for that command should be a table format, with count and name in columns respectively.

When this report is run, you end up with a text file like this:

1/5/2010 – Total Checkins: 3

Count Name
—– —-
2 Name1
1 Name2

1/6/2010 – Total Checkins: 2

Count Name
—– —-
2 Name1


The final report was basically outputting every detail about a changeset into a text file.

Get-TfsItemHistory "$/PROJECTNAME" -Recurse -Version "D1/1/10~D12/31/10" | Sort CreationDate | % {"<code>nChangeSetId - $($_.ChangeSetId), $($_.Committer), $($_.CreationDate) </code>n"; $(Get-TfsChangeset $_.ChangeSetID).Changes | select-tfsitem | select path | Format-Table -Wrap -Auto} | out-file "fullWithPaths.txt"

This script takes a while to run due to the fact that for every changeset, it’s pulling back all of the files modified in that changeset.  Inside of the ForEach we use the second cmdlet Get-TfsChangeset to get the specifics for a changeset, specifically the items changed and we’re selecting the path of those items.  The output looks like this:

ChangeSetId – 21719, edfrey, 01/05/2010 10:43:32


The source for these scripts is also available on GitHub.


What problems have you solved with the TFS powershell cmdlets?


Categories: Coding Tags: ,

Custom build and deployment number for a TFS 2010 Build Farm

May 20th, 2012 No comments

When we do a deployment to QA or UAT, we use MSIs that have been generated by a TFS build server.  This has solved a number of problems for us, not the least of which is repeatability and auditability of the build process.  This is a very important aspect as we hand off the build and deployment processes to our clients.   In future posts, I’ll cover how we tackled generating MSIs from team build.  For this post, I’ll cover the first problem we had to solve: how to generate a consistant version across the build farm.

In the TFS 2010 workflow, the first thing that happens is the build information is generated, the second thing, is that it generates the build number.  Because this happens so early in the process, you cannot store the version number in source control.  There are solutions that I’ve seen that have you store the information in a file on the build server or on a network drive.   Those seemed like a maintenance nightmare as we’re currently supporting 6 build controllers, 40 agents, and almost 100 projects. The option that we settled on was to store the build numbers in a database.

The first thing to do was to create a custom activity to pull the build number from a table.

public sealed class GetBuildNumberFromDatabase : CodeActivity
public InArgument ConnectionString{get;set;}
public InArgument SearchTag{get;set;}
public OutArgument VersionNumber{get;set;}
protected override void Execute(CodeActivityContext context)
int major = 0, minor = 0, build = 0, revision = 0;
GetBuildNumber(context, out major, out minor, out build, out revision);
catch (SqlException ex)
context.TrackBuildError("There was an error retrieving the build number: " + ex.Message);
VersionNumber.Set(context, CreateBuildString(context,major, minor, build, revision));

The HostEnvironmentOption needs to be the controller because the build number is generated on the controller. We pass in the connection string and a search tag and the action gives us back the concatenated build number.   The search tag allows us to create any number of builds using the same database with only having to modify the build metadata.

The build activity will also increment the version number in the database, so we don’t have to manually keep track of where we are (not shown).

The next step, after the GetBuildNumberFromDatabase task was complete, was to drop the new step into the build workflow.  Since this workflow will be used by non-deployment builds as well, where the build number is irrelevant, we added a flag to switch between the built in build number generator and the database version.

The final setup workflow looks like this:

After the addition of the metadata to the build workflow, the process tab of the build definition has the following additions:

  • The full code for the activity can be found on GitHub.
  • If you need assistance in creating the activity and adding it to your workflow, I suggest this blog post by Jim Lamb as a good starting reference.
  •  I also have created this NuGet package to help in setting up the needed references in visual studio.

How do you handle deployment builds and the build number versioning?

Categories: Coding Tags: ,