Wednesday, August 7, 2013

Migrating TFS (2010 or 2012) Personal Queries from one project to another via Powershell

The powershell script below can be saved run on a users system to migrate their personal TFS Queries from one project to another.  This is useful when migrating from TFS 2010 to TFS 2012.

You will need to update the script Source and Target Server URLs, TPC and Projects.  I went down the path to hard code them and not take them as arguments so users did not have to enter anything.  The script will throw errors if the query being migrated is not valid on the target project.
function ProcessQueryItem ($queryFolder, $parentFolder, $sourceProjectName)
{
 $newItem = $null
 foreach ($subQuery in $queryFolder)
 {
  if ($subQuery -is [Microsoft.TeamFoundation.WorkItemTracking.Client.QueryFolder])
  { 
   $newItem = new-object Microsoft.TeamFoundation.WorkItemTracking.Client.QueryFolder -ArgumentList    @($subQuery.Name)
   if (-not $parentFolder.Contains($subQuery.Name))
   {
    Write-Host "Adding Query Folder $subQuery"
    $parentFolder.Add($newItem);
    $WIStoreRight.Projects[$RightProject].QueryHierarchy.Save()
    ProcessQueryItem $subQuery $newItem $sourceProjectName
   }
   else
   {
    Write-Host "Query Folder "$subQuery.name" already exists" -foregroundcolor Yellow
   }

  }
  else
  {
   Write-Host "Creating query "$subQuery.Name
   $oldDef = [Microsoft.TeamFoundation.WorkItemTracking.Client.QueryDefinition]$subQuery
   $queryText = $oldDef.QueryText.Replace("$sourceProjectName\", "$RightProject\")
   $queryText = $queryText.Replace("[System.IterationPath] under '" + $sourceProjectName + "'", "[System.IterationPath] under '" + $RightProject +"'");
   $newItem = new-object Microsoft.TeamFoundation.WorkItemTracking.Client.QueryDefinition -ArgumentList @($subQuery.Name,$queryText)
      
    if ($parentFolder.Contains($subQuery.Name) -ne $true )
    {
    $parentFolder.Add($newItem)
    $WIStoreRight.Projects[$RightProject].QueryHierarchy.Save()
    }
    else
    {
    Write-Host "Query Definition $subQuery already exists" -foregroundcolor Yellow
    }
  
  }
 }
}

[URI]$Projecturileft = "http://sourceServer:8080/tfs/SourceTPC/"
$leftProject = "SourceProject"
[URI]$ProjecturiRight = "http://targetServer:8080/tfs/TargetTPC/"
$RightProject = "TargetProject"

[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.TeamFoundation.WorkItemTracking.Client')
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.TeamFoundation.Client')
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.TeamFoundation.Server')

$tfsleft = [Microsoft.TeamFoundation.Client.TeamFoundationServerFactory]::GetServer($Projecturileft) 
$WIStoreleft = $tfsleft.GetService([Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemStore]) 
$WIStoreleft.RefreshCache($true)
$WIStoreleft.SyncToCache() | out-null

$LeftQuerystore = $WIStoreleft.Projects[$LeftProject].QueryHierarchy

$tfsRight = [Microsoft.TeamFoundation.Client.TeamFoundationServerFactory]::GetServer($ProjecturiRight) 
$WIStoreRight = $tfsRight.GetService([Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemStore]) 
$WIStoreRight.RefreshCache($true)
$WIStoreRight.SyncToCache() | out-null
foreach ($queryFolder in $LeftQuerystore)
{
 if ($queryFolder.IsPersonal)
 {
  $RightMyQueriesFolder = [Microsoft.TeamFoundation.WorkItemTracking.Client.QueryFolder]$WIStoreRight.Projects[$RightProject].QueryHierarchy["My Queries"];
  
  ProcessQueryItem $queryFolder $RightMyQueriesFolder $leftProject
  Write-Host "Personal Queries Migrated"
 }
}

No comments: