There have been occasions where I've wanted to create work items in bulk.
For example: Every time you create a User Story your team has several standard Tasks that need to be created. Write Test Cases, Execute test cases, Deploy to QA, etc. I don't want to manually go through dozens or work items adding the same set of work items as children to each one over and over.
Excel is a pretty good option, certainly faster than doing it one at a time via Team Explorer or the Web interface. In the past I have written C# applications to do this through the TFS API. This works great and is very easy to code.
I am always trying to force myself to get better with PowerShell, so I started searching for examples of calling the TFS API from PowerShell. This helped me piece together the parts I needed to solve this problem with PowerShell.
These were my requirements:
As you can see a simple cut and paste in Excel won't do, because I would still have to edit each work item to add the report name to the title and populate the fields from the parent that I want brought over.
PowerShell to the rescue
if ( (Get-PSSnapin
-Name
Microsoft.TeamFoundation.PowerShell
-ErrorAction
SilentlyContinue) -eq
$null )
{ Add-PSSnapin
Microsoft.TeamFoundation.PowerShell }
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Client")
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Build.Client")
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Build.Common")
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.WorkItemTracking.Client")
#Get the TFS Collection
$tfsCollectionUrl
=
"http://Server:8080/tfs/CollectionName"
$teamProjectCollection
=
[Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory]::GetTeamProjectCollection($tfsCollectionUrl)
#Get the WorkItemStore Service
$ws
=
$teamProjectCollection.GetService([type]"Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemStore")
#Get the Team Project
$proj
=
$ws.Projects["Team Project"]
Write-Host
"Team Project Collection: "$teamProjectCollection
Write-Host
"Project:"
$proj.Name
Write-Host
"---------------------"
#Write a query to get the parent work items
$ParentWorkItems
=
$ws.Query("SELECT [System.Id] FROM WorkItems WHERE [System.AssignedTo] = 'Dave Lloyd' ")
#the Sub Stories you want to create as Children
$ChildStoryTitles
= @( "Report Attributes","Data Lineage","Gap Analysis","Impact Analysis","Remediation","Testing")
#For each Parent Work item
foreach ($WorkItemParent
in
$ParentWorkItems)
{
$counter=1
Write-Host
"Parent workItem:"
$WorkItemParent.ID "-" $WorkItemParent.Title
#For each Parent create 6 New User Stories
foreach ($childTitle
in
$ChildStoryTitles)
{
$story
=
$proj.WorkItemTypes["User Story"]
$workitemChild
=
$story.NewWorkItem()
#Append the Parent Title to the end of the Child Title
#System fields like title can be referenced directly and show up in intelliSence
$workItemChild.Title = $childTitle
+
" for "
+
$WorkItemParent.Title
#There is an order so I used a counter to set the Stack Rank on the CHild Stories
#For non-system fields use the fields member the name of the field and the value property
$workItemChild.Fields["Stack Rank"].value =
$counter
#take any fields from the parent that you want to bring down into the child
$workItemChild.AreaId = $WorkItemParent.AreaId
$workItemChild.Save()
Write-Host
" Child workItem"
$workitemChild.ID $WorkItemChild.Title
#Link the CHild work item to the Parent Work item
$linkType
=
$ws.WorkItemLinkTypes[[Microsoft.TeamFoundation.WorkItemTracking.Client.CoreLinkTypeReferenceNames]::Hierarchy]
$link
=
new-object
Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemLink($linkType.ReverseEnd, $workitemParent.ID)
$workitemChild.Links.Add($link)
$workItemChild.Save()
$counter++
}
}