我最近在TFS 2010
尝试创建了一些自定义签到策略,我创建了一个DLL并添加了一个注册表项,如以下链接所示:
https://msdn.microsoft.com/en-us/library/bb668980.aspx
(注意:我已经知道此链接已停用,但我无法按此处显示的更新方式执行此操作:http://blogs.msdn.com/b/jimlamb/archive/2010/03/31/how-to-implement-package-and-deploy-custom-check-in-policy-for-tfs-2010.aspx)
我并不一定希望我自己的DLL从功能意义上讲从一开始就能正常工作,但步骤4只显示开箱即用的策略,我的不可用。
什么可能导致我的不出现?下面是我正在使用的代码(我已经删除了它实际上做的事情,因为我觉得这不重要)
[Serializable]
public class CheckInPolicy : PolicyBase
{
private string _status = string.Empty;
public override string Description
{
get { return "My description"; }
}
public override string Type
{
get { return "My type"; }
}
public override string TypeDescription
{
get { return "My type description"; }
}
public override bool Edit(IPolicyEditArgs policyEditArgs)
{
return true;
}
public override PolicyFailure[] Evaluate()
{
// Check if the check in meets the policy rules
// ...
// ...
// ...
}
public override void Activate(PolicyFailure failure)
{
base.Activate(failure);
}
public override void DisplayHelp(PolicyFailure failure)
{
MessageBox.Show(
"My policy help notification", "Policy Help");
}
}
This link提到如果操作系统是x64,则需要将策略放在不同的注册表路径中,但我使用的服务器是32位Windows Server 2003计算机。密钥放在:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\TeamFoundation\SourceControl\Checkin Policies]
答案 0 :(得分:1)
我猜你有一台64位机器,在这种情况下,正确的注册表项将是32位路径:
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\TeamFoundation\SourceControl\Checkin Policies
除此之外,您通常需要为每个版本的Visual Studio构建策略,因为它还引用了相应的TeamExplorer库。
编辑: 如果您使用插件扩展服务器端,则可以禁止开发人员覆盖策略,从而拒绝所有已覆盖策略的签入。 您需要将DLL置于此TFS路径下(当然,具体取决于您的版本):
Program Files\Microsoft Team Foundation Server 11.0\Application Tier\Web Services\bin\Plugins\
这里是这个插件类的代码(一些引用的DLL只能在TFS服务器上找到)。如果所有文件都在已发布的文件夹中,我们允许覆盖,但您当然可以定义自己的排除项:
using System;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.Framework.Server;
using Microsoft.TeamFoundation.VersionControl.Server;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.TeamFoundation.Framework.Server.Alm;
namespace TFS.CheckinPolicyOverrideEventHandler
{
public sealed class CheckinPolicyOverrideEventHandler : ISubscriber
{
public Type[] SubscribedTypes()
{
return new Type[1] { typeof(CheckinNotification) };
}
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.DecisionPoint && notificationEventArgs is CheckinNotification)
{
CheckinNotification ev = notificationEventArgs as CheckinNotification;
if (ev != null && ev.PolicyOverrideInfo != null)
{
if (ev.PolicyOverrideInfo.PolicyFailures != null)
{
// One or more of the checkin policies have been overridden
// If all the files being checked in are in the published folder, then allow overridding the policies since those are installation packages
foreach (string file in ev.GetSubmittedItems(null))
{
if (!Regex.IsMatch(file, @"/published", RegexOptions.IgnoreCase) &&
!Regex.IsMatch(Path.GetDirectoryName(file), @"/published", RegexOptions.IgnoreCase))
{
statusCode = -1;
break;
}
}
if (statusCode != 0)
{
// One or more of the checkin policies have been overridden and not all files are installation files (in the published folder)
statusMessage = Resource.CheckinCancelledStatusMessage;
foreach (PolicyFailureInfo policy in ev.PolicyOverrideInfo.PolicyFailures)
{
statusMessage = String.Concat(statusMessage, "\n > ", policy.PolicyName, ": ", policy.Message);
}
return EventNotificationStatus.ActionDenied;
}
}
}
return EventNotificationStatus.ActionPermitted;
}
}
catch (Exception exception)
{
// decide what you want to do, if exception occurs
}
return EventNotificationStatus.ActionPermitted;
}
public string Name
{
get { return "TFS.CheckinPolicyOverrideEventHandler"; }
}
public SubscriberPriority Priority
{
get { return SubscriberPriority.Normal; }
}
}
}