Using Team Foundation Server Registry–Part II the API
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 now ) .
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
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/
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.