I was having lunch with an associate a while back and he mentioned a need to move a work item from one team project to another. While there isn’t any direct support for this from the Team Explorer interface, I figured it couldn’t be too hard to manipulate the underlying database and achieve the results - it’s just SQL Server right? I hadn’t actually looked at the schema mind you, I’m an optimist.

It wasn’t quite as simple as I thought - it felt like the database had been designed by the security group and intentionally obscured for privacy. The TFS database is fairly generic (so that it can add arbitrary items into the schema for custom project types) and has been somewhat secured to protect the code itself - the stored procedures are encrypted and SQL Profiler doesn’t give much information on what’s happening.

So, I spent a week or so looking at the schema for the Work Item system and a lot of trial and error. End result is that I got a simple application to move work items around. This application does a couple of other things as well - lists projects, active web services, etc. I was mostly playing with the schema and trying to figure things out. It’s just a console application but it does the job.

Here’s the code, use at your own risk (a.k.a. if it screws up your system, I can’t help you). The source for the simple test project is included so you can see what was done and incorporate it into your own code base if you like.

The program is fairly easy to use - a binary is included with the release. Issuing the command with no parameters generates a simple “Help” page –

C:WorkTfsCmd> **tfscmd**
TfsCmd [command] [/t tfsserver] [/u user] [/p password] [params]  
ListProjects - Lists the active projects on the TF server.  
TfsCmd ListProjects  
ListServices - Displays the web services exposed by the TF server.  
TfsCmd ListWebServices  
WQL - Execute a WorkItem Query.  
TfsCmd Wql [query]  
MoveWorkItem - Moves a work item from one Team Project to another  
TfsCmd MoveWorkItem [id] [ProjectName]

Executing a command will use your logged on user/password (domain credentials) unless you supply a /u and /p parameter. For example, running the ListProjects command generates something like:

C:WorkTfsCmd> **tfscmd ListProjects**
Project Name: Test  
Status: WellFormed  
Guid: 8c5b175b-b0ef-46bb-9a9e-dde05bb145ac  
Process Template: MSF for Agile Software Development - v4.0  
Defined Properties: MSPROJ  

Listing the web services just hits the underlying database to get the information:

C:WorkTfsCmd> **tfscmd ListServices**
BuildStoreService = http://(local):8080/Build/v1.0/BuildStore.asmx  
BuildControllerService = http://(local):8080/Build/v1.0/BuildController.  
IBISEnablement = http://(local):8080/Build/v1.0/Integration.asmx  
LinkingProviderService = http://(local):8080/Build/v1.0/Integration.asmx  
IProjectMaintenance = http://(local):8080/Build/v1.0/Integration.asmx  
PublishTestResultsBuildService = http://(local):8080/Build/v1.0/PublishT tsBuildService.asmx  

Moving work items is fairly easy - just provide the work item id (the numeric identifier) and the new project name - this must match an existing project in your TFS system. The tool will attempt to match up the iteration to a value in the new project - if it cannot, it will default to the first iteration available.

C:WorkTfsCmd> **tfscmd MoveWorkItem 1 "Mark's New Project"**  
Work Item #1: "Create Project Definition" is currently located in project "Test Project (Iteration 0)"  
Moving work item to "Mark's New Project (Iteration 0)"  

If you have the TFS client open, then you should shut it down and reopen it before modifying the moved work item - the client appears to cache bits of information and I had some issues with moved items if I didn’t clear the cache by closing the work item window and reopening it.

Have fun!