Jaa


get-tfs.ps1 - example of adding properties to make interactive life easier

One of the things I noticed while working inside PowerShell was wanting to make a quick TFS object model (OM) call (for instance, to VersionControlServer) and slice/data/inspect the results.  The OM calls to get an instance of TeamFoundationServer aren't bad (first load the assembly, then just call the ctor or use the factory class), and getting the VersionControlServer from there isn't bad (load the assembly, then GetService the type), but they weren't "very" scripting-friendly, so here's a simple wrapper for them.

Currently it just adds 4 properties to the TeamFoundationServer instance, for a little easier access to the particular interfaces I find myself using the most.  Of course, you can add/remove entries from these (or just not add them at all, of course).  For each of them, it generates the script block to execute for that property, then uses add-member to attach it.  Of course, we're not really changing the TeamFoundationServer type on the fly, but the PsObject mechanics make it look like that, which is really slick and useful :)

With this script, I can fetch an instance with " $tfs = get-tfs https://tkbgitvstfat01:8080" (substitute your server name or URL, of course) and then make OM calls easily.  Since we're in PowerShell, I can take the output of these calls and do lots of fun filtering and inspection.  Here are a few simple examples - hopefully it's clear that this is far easier than having to call tf.exe and do the cut/awk/sed/grep/findstr kinds of work you normally would deal with in a cmd/bash/whatever world.

Note that the actual useful functionality (Version Control, Work Item Tracking, etc.) was always there, of course, the only real thing this script does it make it a little easier to get at it.  Also, there are far more useful services offered by TeamFoundationServer than just these 4, but I wanted to keep the example simple, but still useful.

Use VersionControlServer (VCS) to find the top-level folder with the longest name

C:\> $tfs.vcs.GetItems('$/*').Items | sort -desc { $_.serveritem.length } | select -first 1 | fl serveritem,checkindate,changesetid

ServerItem : $/Developer Division Product Scope
CheckinDate : 5/30/2006 1:08:36 PM
ChangesetId : 74756

Use CommonStructureService (CSS) to show all the team projects that have 'VSTS' in the name

C:\> $tfs.css.listallprojects() | ?{ $_.Name -match 'VSTS' } | fl

Uri : vstfs:///Classification/TeamProject/180e1e5d-bbe8-418a-b9a4-152026964fb4
Name : VSTS V2 Plans
Status : WellFormed

Uri : vstfs:///Classification/TeamProject/365f4f53-9e05-4ded-9c21-52e9d9de978a
Name : VSTS Architecture Group
Status : Deleting

Uri : vstfs:///Classification/TeamProject/7c0d0a50-e31a-4bed-8e48-a99bc95def95
Name : VSTS Dogfood
Status : WellFormed

Uri : vstfs:///Classification/TeamProject/76a10abd-b3be-4803-9efc-d2a9d219885a
Name : VSTS Community
Status : WellFormed

Use WIT to check out the links from a work item and who created it when

C:\> $tfs.wit.getworkitem(99000) | fl links,CreatedBy,CreatedDate

Links : {100701, 99473, 95514}
CreatedBy : Doug Mortensen
CreatedDate : 5/22/2006 7:26:09 PM

Use GSS to look up my display name and email address

C:\> $tfs.gss.ReadIdentity('accountname', 'NORTHAMERICA\jmanning', 'none') | fl displayname,mailaddress

DisplayName : James Manning
MailAddress : james.manning@microsoft.com

Use GSS to count the number of direct members in a security group

C:\> $tfs.gss.ReadIdentity('accountname', 'REDMOND\burtonall', 'direct').members.count
6

 

 param(
    [string] $serverName = $(throw 'serverName is required')
)

begin
{
    # load the required dll
    [void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Client")

    $propertiesToAdd = (
        ('VCS', 'Microsoft.TeamFoundation.VersionControl.Client', 'Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer'),
        ('WIT', 'Microsoft.TeamFoundation.WorkItemTracking.Client', 'Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemStore'),
        ('CSS', 'Microsoft.TeamFoundation', 'Microsoft.TeamFoundation.Server.ICommonStructureService'),
        ('GSS', 'Microsoft.TeamFoundation', 'Microsoft.TeamFoundation.Server.IGroupSecurityService')
    )
}

process
{
    # fetch the TFS instance, but add some useful properties to make life easier
    # Make sure to "promote" it to a psobject now to make later modification easier
    [psobject] $tfs = [Microsoft.TeamFoundation.Client.TeamFoundationServerFactory]::GetServer($serverName)
    foreach ($entry in $propertiesToAdd) {
        $scriptBlock = '
            [System.Reflection.Assembly]::LoadWithPartialName("{0}") > $null
            $this.GetService([{1}])
        ' -f $entry[1],$entry[2]
         $tfs | add-member scriptproperty $entry[0] $ExecutionContext.InvokeCommand.NewScriptBlock($scriptBlock) 
    }
    return $tfs
}

get-tfs.ps1

Comments

  • Anonymous
    September 28, 2006
    Great stuff James!

    Very useful.

  • Anonymous
    September 29, 2006
    Along with easier TeamFoundationServer access, one of the things I found myself wanting was easier access...

  • Anonymous
    November 17, 2006
    Did a little script this week that updates one work item (the "feature") based on summing values in other

  • Anonymous
    January 30, 2007
    I was trying to modify a work item today and put in, apparently, too much text into a field I really

  • Anonymous
    February 13, 2007
    [note: all my scripts are now zip'd up together on this page ] This particular script probably isn't

  • Anonymous
    February 21, 2007
    One thing that's missing from PowerShell is the ability to import foreign namespaces into the current

  • Anonymous
    March 30, 2009
    PingBack from http://get-powershell.com/2008/11/14/powershell-and-tfs-work-items/

  • Anonymous
    April 10, 2009
    Fun with PowerShell and TFS Work Items

  • Anonymous
    May 29, 2009
    PingBack from http://paidsurveyshub.info/story.php?title=james-manning-s-blog-get-tfs-ps1-example-of-adding-properties-to