Tuesday, May 31, 2011

Mashup: Team Foundation Server's API and Microsoft Active Directory

I wanted to know the userID and name of anyone that checked out a file in the last 2 months for edit on a specific path inside Tfs. Some of this code was tested to work fine on Tfs2010, but no guarantees.

So it's a nice little bit of code to connect to tfs, get the changes and then pull the names in from active directory with a max of 1 attempt per distinct userID.




//imports: 
//Microsoft.TeamFoundation.Client
//Microsoft.TeamFoundation.VersionControl.Client
//System.DirectoryServices
void Main()
{
 
  Uri tfs08Uri= new Uri("http://tfs.yourtfs.com:8080"); //TODO:this will be specific to your query
  
  
  using(var tfsPc=new TfsTeamProjectCollection(tfs08Uri))
  
  {
  
    var vcs=tfsPc.GetService<Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer>();
   
    var gtpm=vcs.GetItem("$/yourServerPath"); //TODO:this will be specific to your query
    
    
    var pendings=vcs.QueryPendingSets(new[]{gtpm.ServerItem}, RecursionType.Full,null,null);
    var pendingQuery=pendings.Where(p=>p.PendingChanges
        .Any(pc=>pc.CreationDate>DateTime.Today.AddMonths(-2))) 
      .OrderByDescending(p=>p.PendingChanges.Max(d=>d.CreationDate));
      
    var q= from pq in pendingQuery
        from pc in pq.PendingChanges
        where pc.FileName.EndsWith(".refresh")==false
        select new{pq.OwnerName,pq.Computer,pc.ServerItem,pc.CreationDate,pc.FileName};
        var users=q.Select(u=>u.OwnerName).Distinct();
        var joinedQuery= from pc in q
          join l in lookup(users).ToList() on pc.OwnerName equals l.Key into luLeft
          from lu in luLeft.DefaultIfEmpty()
          select new {Name=lu.Value??pc.OwnerName,pc.FileName,pc.ServerItem,pc.CreationDate,pc.Computer,pc.OwnerName};
          joinedQuery.Dump();

        
  
    
  }
}

public static IEnumerable<KeyValuePair<string,string>> lookup(IEnumerable<string> ids)
{


using(var de=new System.DirectoryServices.DirectoryEntry())
{
  var customPath="LDAP://DC=corp,DC=yourdomain,DC=com"; //TODO:this will be specific to your ActiveDirectory
  de.Path=customPath;
  de.AuthenticationType= System.DirectoryServices.AuthenticationTypes.Secure;
  
  using(var deSearch=new System.DirectoryServices.DirectorySearcher())
  {
    deSearch.SearchRoot=de;
    var found=new Dictionary<string,string>( StringComparer.CurrentCultureIgnoreCase);
    foreach(var ownerName in ids)
      {
      if(found.ContainsKey(ownerName))
      yield return  found.First(k=>k.Key==ownerName);
      deSearch.Filter="(&(objectClass=user)(SAMAccountName="+ownerName+"))";
      string value;
      try
      {          
        var me=deSearch.FindOne();  
        value= me.Properties["name"][0].ToString();
        //value.Dump();
      }
      catch(Exception)
      {
        value= null;
      }
       found.Add(ownerName,value);
      yield return new KeyValuePair<string,string>(ownerName,value);
    }
  }
}
}
//references:
//%windir%\Microsoft.Net\Framework\v4.0.30319\System.DirectoryServices.dll
//%ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.TeamFoundation.Common.dll
//%ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.TeamFoundation.Client.dll
//%ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.TeamFoundation.VersionControl.Common.dll
//%ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.TeamFoundation.VersionControl.Client.dll


Done in LinqPad

Extra snippets/remnants leftover for anyone interested:
//var exclusionList=new [] {"*.suo","*.gpstate","svn","_svn",".svn","*Resharper*"};
    //  vcs.GetItems("$/yourServerSpec/*.suo/", Microsoft.TeamFoundation.VersionControl.Client.RecursionType.Full).Items //TODO: this will be specific to your query
    //    .Select(i=>i.ServerItem).Distinct().Dump();
    //var workspaces=vcs.QueryWorkspaces(null,null,null).Where(w=>w.IsLocal==false & w.LastAccessDate>DateTime.Now.AddDays(-15)).Where(w=>w.Folders.Any(f=> f.ServerItem.StartsWith("$/PST")));
    //workspaces.OrderByDescending(w=>w.LastAccessDate).Dump(1);
//  var checkins=vcs.GetBranchHistory(new ItemSpec[]{new ItemSpec( gtpm.ServerItem, RecursionType.Full)},VersionSpec.Latest);
  //  checkins.Count().Dump();

1 comment:

  1. Great !

    How use LinqPad using TeamFoundationClient?

    Who are Gurus about TFS now ? Eugene , Richard Berg, Tarun Arora, ... not updates in his blogs :'(

    IMHO, the more complete unit test like this:

    Create Team Project
    Create WorkSpace
    Mapping local folder for Workspace
    Include files in Source Control (in those Workspace and TeamProject)
    Check Out file
    Check In file
    Create Branch
    View History
    Merge
    View History (Branchs, Merges, Changes..)
    Delete Branch
    Delete Mappings
    Delete WorkSpace
    Delete Team Project

    ReplyDelete