2011-03-01 91 views
8

我希望TFS 2010在发生特定工作流程转换时运行一些自定义代码。那可能吗?TFS在工作项目转换时执行自定义代码

我发现文档有关自定义操作,这似乎是可以自动触发工作项转变(我会收到这样吗?)的行动我也发现了自定义活动,这些都与构建。但没有任何符合这个特殊要求的东西 - 我错过了什么?

感谢您的帮助!

回答

14

这是非常可行的。

这是可行的,有很多方法可以做到这一点。我的最爱之一是制作服务器端插件。 (请注意,这仅适用于2010年TFS)

这些博客文章显示的基本知识:

下面是一些代码,我从开源修改项目TFS Aggregator

public class WorkItemChangedEventHandler : ISubscriber 
{  
    /// <summary> 
    /// This is the one where all the magic starts. Main() so to speak. 
    /// </summary> 
    public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs, 
               out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties) 
    { 
     statusCode = 0; 
     properties = null; 
     statusMessage = String.Empty; 
     try 
     { 
      if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent) 
      { 
       // Change this object to be a type we can easily get into 
       WorkItemChangedEvent ev = notificationEventArgs as WorkItemChangedEvent; 
       // Connect to the setting file and load the location of the TFS server 
       string tfsUri = TFSAggregatorSettings.TFSUri; 
       // Connect to TFS so we are ready to get and send data. 
       Store store = new Store(tfsUri); 
       // Get the id of the work item that was just changed by the user. 
       int workItemId = ev.CoreFields.IntegerFields[0].NewValue; 
       // Download the work item so we can update it (if needed) 
       WorkItem eventWorkItem = store.Access.GetWorkItem(workItemId); 

       if ((string)(eventWorkItem.Fields["State"].Value) == "Done") 
        { 
         // If the estimated work was changed then revert it back. 
         // We are in done and don't want to allow changes like that. 
         foreach (IntegerField integerField in ev.ChangedFields.IntegerFields) 
         { 
          if (integerField.Name == "Estimated Work") 
          { 
           eventWorkItem.Open(); 
           eventWorkItem.Fields["Estimated Work"].Value = integerField.OldValue; 
           eventWorkItem.Save(); 
          } 
         } 
        } 
       } 
      } 

     } 
     return EventNotificationStatus.ActionPermitted; 
    } 

    public string Name 
    { 
     get { return "SomeName"; } 
    } 

    public SubscriberPriority Priority 
    { 
     get { return SubscriberPriority.Normal; } 
    } 

    public WorkItemChangedEventHandler() 
    { 
     //DON"T ADD ANYTHING HERE UNLESS YOU REALLY KNOW WHAT YOU ARE DOING. 
     //TFS DOES NOT LIKE CONSTRUCTORS HERE AND SEEMS TO FREEZE WHEN YOU TRY :(
    } 

    public Type[] SubscribedTypes() 
    { 
     return new Type[1] { typeof(WorkItemChangedEvent) }; 
    } 
} 

/// <summary> 
/// Singleton Used to access TFS Data. This keeps us from connecting each and every time we get an update. 
/// </summary> 
public class Store 
{ 
    private readonly string _tfsServerUrl; 
    public Store(string tfsServerUrl) 
    { 
     _tfsServerUrl = tfsServerUrl; 
    } 

    private TFSAccess _access; 
    public TFSAccess Access 
    { 
     get { return _access ?? (_access = new TFSAccess(_tfsServerUrl)); } 
    } 
} 

/// <summary> 
/// Don't use this class directly. Use the StoreSingleton. 
/// </summary> 
public class TFSAccess 
{ 
    private readonly WorkItemStore _store; 
    public TFSAccess(string tfsUri) 
    { 
     TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(new Uri(tfsUri)); 
     _store = (WorkItemStore)tfs.GetService(typeof(WorkItemStore)); 
    } 

    public WorkItem GetWorkItem(int workItemId) 
    { 
     return _store.GetWorkItem(workItemId); 
    } 
} 
+2

要注意的一件重要的事情是,这个事件是一个通知(而不是一个决定点)。这意味着你没有办法阻止它。你只能对它做出反应。 – Vaccano 2011-03-02 00:08:07

+0

这正是我正在寻找的。非常感谢。 – 2011-03-02 14:05:17

+0

@Vaccano - 您的[TFS聚合器](http://tfsaggregator.codeplex.com/)项目对我们的团队非常有用。只是想表示感谢......我现在正在使用Codeplex的项目来传播最新的成果! – 2013-02-12 11:56:33

0

这里是我的单例模式的一个例子

public class TFSSingleton 
{ 
    private static TFSSingleton _tFSSingletonInstance; 
    private TfsTeamProjectCollection _teamProjectCollection; 
    private WorkItemStore _store; 

    public static TFSSingleton Instance 
    { 
     get 
     { 
      if (_tFSSingletonInstance == null) 
      { 
       _tFSSingletonInstance = new TFSSingleton(); 
      } 
      return _tFSSingletonInstance; 
     } 
    } 

    public TfsTeamProjectCollection TeamProjectCollection 
    { 
     get { return _teamProjectCollection; } 
    } 

    public WorkItemStore RefreshedStore 
    { 
     get 
     { 
      _store.RefreshCache(); 
      return _store; 
     } 
    } 

    public WorkItemStore Store 
    { 
     get { return _store; } 
    } 

    private TFSSingleton() 
    { 
     NetworkCredential networkCredential = new NetworkCredential("pivotalautomation", "*********", "***********"); 


     // Instantiate a reference to the TFS Project Collection 
     _teamProjectCollection = new TfsTeamProjectCollection(new Uri("http://********:8080/tfs/**********"), networkCredential); 
     _store = (WorkItemStore)_teamProjectCollection.GetService(typeof(WorkItemStore)); 
    } 
} 

这里是它是如何被引用的。

WorkItemTypeCollection workItemTypes = TFSSingleton.Instance.Store.Projects[projectName].WorkItemTypes;