In my first post in this series I showed an msbuild script that would create a Team Foundation Server source control workspace, get latest to a particular folder, and build the Visual Studio solution in one click. However, because of the fact that TFS v.1 does not allow shared workspaces, the script wouldfail if another developer is already has a workspace mapped to that folder. I needed a way to delete all workspaces of a certain name.
There are two tf.exe (command line tool for TFS) commands that are useful here:
Lists all workspaces by any user of a certain name:
tf workspaces [workspacename] /owner:*
Deletes a workspace for a specific user:
tf workspace /delete [workspacename];username /noprompt
There’s no way to automatically pipe information from the first command into the second, to automatically delete another user’s workspace. The way I worked around this was to create a custom MSBuild task that used the TFS C# API…
using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
namespace EmergeMD.MSBuild.Tasks
{
/// <summary>
/// Will delete all workspaces with a particular name. This way a workspace can be recreated and mapped to a different user in a build script. Use this with caution, since it will delete any shelved changes in this workspace. I’ve found this useful for a build server type configuration, where multiple developers can log in and update the code by hand by simply clicking an msbuild script. This workaround is tied to the fact that you can’t have shared workspaces.
/// </summary>
/// <example>
/// <UsingTask TaskName=”EmergeMD.MSBuild.Tasks.DeleteWorkspaceByNameTask”
/// AssemblyFile=”EmergeMD.MSBuild.Tasks.dll”/>
/// <DeleteWorkspaceByNameTask WorkspaceName=”$(WorkspaceName)” TeamFoundationServerUrl=”$(ServerName)” ContinueOnError=”false” />
/// </example>
public class DeleteWorkspaceByNameTask : Task
{
private string _workspaceName;
[Required]
public string WorkspaceName
{
get { return _workspaceName; }
set { _workspaceName = value; }
}
private string _teamFoundationServerUrl;
[Required]
public string TeamFoundationServerUrl
{
get { return _teamFoundationServerUrl; }
set { _teamFoundationServerUrl = value; }
}
public override bool Execute()
{
Log.LogMessage(“Preparing to delete workspaces named “ + WorkspaceName);
TeamFoundationServer server = TeamFoundationServerFactory.GetServer(TeamFoundationServerUrl);
VersionControlServer serverVc = (VersionControlServer) server.GetService(typeof (VersionControlServer));
try
{
Workspace[] workspaces = serverVc.QueryWorkspaces(WorkspaceName, null, null);
foreach(Workspace workspace in workspaces)
{
serverVc.DeleteWorkspace(workspace.Name, workspace.OwnerName);
Log.LogMessage(
string.Format(“Deleted workspace {0} mapped to {1}”, workspace.Name, workspace.OwnerName));
}
return true;
}
catch (Exception e)
{
Log.LogError(“This task failed to delete workspace by filepath: “ + e.Message);
return false;
}
}
}
}
—-
Some useful references here:



0 Responses to “TFS & MSBuild Part 3 (custom msbuild task)”