Using Team Foundation Server Registry–Part II the API

3 minute read

 

On the first part of this series I talked about what is the registry and some basic scenarios usage, on this post I want to talk about how you manipulate registry entries.

You have two choices, using an utility to manipulate entries or using TFS object model (or SDK as it is officially called) using a .Net language or Powershell

Using an utility

Neno Loje wrote tfsreg.exe that you can use to manipulate (both read and write) registry values.

You can see an example of how to use it on a blog post  where Neno explains how to change the email notification delay (a setting that is stored in the configuration registry)

You can download the tool from the mentioned post.

Note: Although it is not clear on the post or on the utility itself, this tool only allows you to manipulate registry entries from the configuration registry (at least for nowSmile ) .

Reading/Writing values

All code is using the client object model, but most (if not all) calls also have a counterpart server object model that can be used on server scenarios.

You can manipulate registry entries using the ITeamFoundationRegistry interface.

Assuming you are already connected to TFS and have in your possession a valid reference to

TfsTeamProjectCollection object all you need to do to get a value is this (assuming you have enough permissions)

ITeamFoundationRegistry service = tfs.GetService<ITeamFoundationRegistry>();

service.GetValue(key);

You can also have at your disposal the generic methods GetValue there are also overloads that can return a default value if the key is not found (OR you don’t have permissions to read it)

To write a value all you need is to use the SetValue member.

Pretty simple huh?

This is to access the a project collection registry, if you want to access the configuration registration instead you (if you have a connection to a project collection) you can get a reference like this

var regService = tfs.ConfigurationServer.GetService<ITeamFoundationRegistry>();

All the rest remains equal (you can also connect directly to the server using the class TfsConfigurationServer and then obtaining a reference to ITeamFoundationRegistry

Setting Permissions

Setting permissions requires a bit of more work,since there are (that I know of) not utilities to do this. It is still simple anyways. In order to read/set/remove a permission you need to use SecurityNamespace to manipulate objects from Registry Namepace, we can obtain it  via ISecurityService.

So in order to get a security namespace that can manipulate permissions from registry objects you need to something like this snippet:

var server = tfs.GetService<ISecurityService>();
var securityNamespace = server.GetSecurityNamespace(FrameworkSecurity.RegistryNamespaceId);

We can then use the SetPermissions method to set out permission, the following snippet

securityNamespace.SetPermissions("/", identity.Descriptor ,RegistryServicePermissions.AllPermissions, 0, true);

Now to dissect these parameters.

The signature for the method is:

public abstract AccessControlEntry SetPermissions(
    string token,
    IdentityDescriptor descriptor,
    int allow,
    int deny,
    bool merge
)

 

  • token paremeter we will pass / which means we will be granting access to the entire registry. If you want to grant just access to a part of the tree, this is the place to do it
  • identityDescriptor we will pass the account/group for which we will be granting the parameter (more on this later)
  • allow parameter we pass the value the value RegistryServicePermissions.AllPermissions since we want to grant read/write access
  • deny parameter we will pass 0 since we don’t wan to deny anything
  • merge we will pass true, since we want this permissions to be merged with existing ones (just in case)

Note: the value 1 and 2 on the allow/deny parameter depends on the type of security namespace we are dealing with, and it can be obtained from the security catalog.

To get and identity descriptor you need to use IIdentityManagementService, this snippet will allow you to get the identity of the group [DefaultCollection]Project Collection Build Service Accounts

var identityService = tfs.GetService<IIdentityManagementService>();

var identity = identityService.ReadIdentity( IdentitySearchFactor.DisplayName, @"[DefaultCollection]Project Collection Build Service Accounts", MembershipQuery.Direct, ReadIdentityOptions.None);

Notice the first parameter is key to the search, you can either search the user by it’s display name or by account name (IdentitySearchFactor.AccountName), but if you use Account name, the account will have to be in the format

vstfs:///Framework/IdentityDomain/<Name>

so using the same example the account name would be

String.Format("vstfs:///Framework/IdentityDomain/{0}\Project Collection Build Service Accounts", tfs.InstanceId.ToString());

It is very important that specify the searchFactorValue in the right format or you won’t find the identity descriptor you are looking for.