我希望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