我希望TFS 2010在发生特定工作流程转换时运行一些自定义代码。那可能吗?TFS在工作项目转换时执行自定义代码
我发现文档有关自定义操作,这似乎是可以自动触发工作项转变(我会收到这样吗?)的行动我也发现了自定义活动,这些都与构建。但没有任何符合这个特殊要求的东西 - 我错过了什么?
感谢您的帮助!
我希望TFS 2010在发生特定工作流程转换时运行一些自定义代码。那可能吗?TFS在工作项目转换时执行自定义代码
我发现文档有关自定义操作,这似乎是可以自动触发工作项转变(我会收到这样吗?)的行动我也发现了自定义活动,这些都与构建。但没有任何符合这个特殊要求的东西 - 我错过了什么?
感谢您的帮助!
这是非常可行的。
这是可行的,有很多方法可以做到这一点。我的最爱之一是制作服务器端插件。 (请注意,这仅适用于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);
}
}
这里是我的单例模式的一个例子
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;
要注意的一件重要的事情是,这个事件是一个通知(而不是一个决定点)。这意味着你没有办法阻止它。你只能对它做出反应。 – Vaccano 2011-03-02 00:08:07
这正是我正在寻找的。非常感谢。 – 2011-03-02 14:05:17
@Vaccano - 您的[TFS聚合器](http://tfsaggregator.codeplex.com/)项目对我们的团队非常有用。只是想表示感谢......我现在正在使用Codeplex的项目来传播最新的成果! – 2013-02-12 11:56:33