0

I've been trying to create some custom check-in policies in TFS 2010 recently, I created a DLL and added a registry key as outlined in the following link: https://msdn.microsoft.com/en-us/library/bb668980.aspx

(Note: I already know this link is retired, but I'm unable to do it in the updated fashion indicated here: http://blogs.msdn.com/b/jimlamb/archive/2010/03/31/how-to-implement-package-and-deploy-custom-check-in-policy-for-tfs-2010.aspx)

I didn't necessarily expect my own DLL to work correctly from the start in a functional sense, but Step 4 only shows the out of the box policies, mine is not available.

What could be causing mine to not appear? Below is the code I'm using (I've removed what it actually does as I don't think that's important)

[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 mentioned that the policy needs to be placed in a different registry path if the OS is x64, but the server I'm using is a 32-bit Windows Server 2003 machine. The key is placed in:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\TeamFoundation\SourceControl\Checkin Policies]

Community
  • 1
  • 1
MattR
  • 641
  • 3
  • 17
  • 38
  • 1
    At a bare minimum, the version number you're using in the registry is not correct. `9.0` refers to VS 2008. For 2010, you want `10.0`. http://blogs.msdn.com/b/tfssetup/archive/2013/11/21/what-version-of-team-foundation-server-do-i-have.aspx – Edward Thomson Feb 12 '15 at 12:32
  • Hey @EdwardThomson when I check the registry under 10.0 there isn't an option for SourceControl\Checkin Policies, it only appears under 9.0 on my server. I guess it's possible that this server is actually running a lower version of TFS. – MattR Feb 12 '15 at 13:40
  • Actually on checking TFS 2010 is installed, VS2008 is the highest version of Visual Studio on the box. – MattR Feb 12 '15 at 14:05

1 Answers1

1

I guess you have a 64-bit machine, in that case the correct registry entry would be the 32-bit path:

    [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\TeamFoundation\SourceControl\Checkin Policies

In addition to this, you usually need to build the Policy for each version of Visual Studio, as it also has references to the appropriate TeamExplorer libraries.

EDIT: You can prohibit developers from overriding policies, if you extend your server side with a plugin, that declines all checkins with overridden policies. You need to place the DLL under this TFS path (of course depending on your version):

Program Files\Microsoft Team Foundation Server 11.0\Application Tier\Web Services\bin\Plugins\

Here the code of this plugin class (some of the referenced DLLs can only be found on TFS servers). We allow to override if all files are in published folder, but you can of course define your own exclusions:

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; }
    }
}

}

MikeR
  • 3,045
  • 25
  • 32
  • Hi @MikeR, unfortunately not, it's a 32-bit machine. So with it having to be built for each version of Visual Studio would I need to have each version installed on the server in order to get the appropriate registry keys? – MattR Feb 13 '15 at 14:03
  • Policies are installed on client side, as they run in the client context. The reason is to offload the task from server to client, as some policies could be very ressource consuming. So you need to have the policy in different versions using the appropriate version of TeamExplorer/VS your clients use. – MikeR Feb 16 '15 at 06:49
  • I see, well I managed to do that so it's visible, not tested it works but that's not what the question is about so I'll do that later. As it's client side I guess there is nothing to stop a developer simply removing the policy and therefore bypassing it? Is there anyway to make it a server side policy? Or at least ensure that it is enforced somehow? – MattR Feb 16 '15 at 17:20
  • A policy can be overwritten by a developer even if the policy is there and active. It is possible to implement a TFS plugin on server-side, which will prohibit to overwrite policies. I will add some more information in my answer. – MikeR Feb 17 '15 at 06:56