Checking which Delegate Controls are activated on your site
Delegate Controls allow you to provide users with pluggable functionality which they can use to extend their existing solution without modifying the existing code. Unfortunately once enabled it’s difficult to track which Delegate Controls are used where on your site. Find out how to check which Delegate Controls are activated on your site using PowerShell.
Delegate Controls 101
Delegate Controls are a great piece of engineering – no doubt about it. Using this capability you can easily extend existing environment with new functionality. And for this all you have to do is to activate a Feature that registers your control with a Delegate Control.
If you take a look at the contents of the standard v4.master Master Page you will find a few Delegate Controls there.
Those controls specify place holders to which your controls can be bound. Some Delegate Controls allow you to bind multiple controls and other only one. In the latest scenario the control with the lowest sequence number is the one that will be registered with the site.
You can register a control with a Delegate Control using the Control element. While registering your control you can either point to an assembly and class or a User Control (ASCX). The following screenshot shows how the Extended Search Box is being registered with the Search Box Delegate Controls:
The standard Search control is a great example of how Delegate Controls can be leveraged to provide different capabilities to the users: depending on which SharePoint license you have and which Features have been activated on your site, you will get a different search box with different capabilities.
A Delegate Control can be as small as a custom control inheriting from the Control class and as large as a complete User Control with complex UI. Such flexibility makes the Delegate Controls capability applicable in many different scenarios.
The Inconvenience
Delegate Controls are a great way of enhancing standard capabilities and they are used quite frequently in custom solutions. However out of the box there is no overview of which Delegate Controls have been registered with the site. So if things go wrong there is no easy way of telling which controls are active and which could be possibly causing the trouble.
The Solution
Luckily using the SharePoint API and PowerShell you can query for all Delegate Controls registered with your site. Take a look at the following PowerShell snippet:
param(
[string]$Url,
[string]$ControlId,
[switch]$AllowMultiple
)
function Get-DelegateControls {
param(
[string]$Url,
[string]$ControlId,
[bool]$AllowMultiple
)
$allDelegates = Get-AllDelegateControls $Url
if ($ControlId) {
$allDelegates = $allDelegates | Where { $_.Id -eq $ControlId }
if (-not($AllowMultiple)) {
$allDelegates = $allDelegates[0]
}
}
$allDelegates | Sort Id, Sequence
}
function Get-AllDelegateControls {
param(
[string]$Url
)
$web = Get-SPWeb $Url
$culture = New-Object System.Globalization.CultureInfo([int]$web.Language, $false)
Get-DelegateControlElements $web.Features $culture
Get-DelegateControlElements $web.Site.Features $culture
Get-DelegateControlElements $web.Site.WebApplication.Features $culture
$farmFeatures = [Microsoft.SharePoint.Administration.SPWebService]::ContentService.Features
Get-DelegateControlElements $farmFeatures $culture
}
function Get-DelegateControlElements {
param (
[Microsoft.SharePoint.SPFeatureCollection]$Features,
[System.Globalization.CultureInfo]$Culture
)
$farm = Get-SPFarm
foreach ($feature in $Features) {
$featureDefinition = $farm.FeatureDefinitions[$feature.DefinitionId]
if ($featureDefinition -ne $null) {
$elementDefinitions = $null;
try {
$elementDefinitions = $featureDefinition.GetElementDefinitions($Culture)
}
catch { }
foreach ($elementDefinition in $elementDefinitions) {
if ($elementDefinition.ElementType -eq 'Control') {
$elementDefinition
}
}
}
}
}
Get-DelegateControls $Url $ControlId $AllowMultiple
This script can be used in a couple scenarios. First of all it allows you to query all Delegate Controls which are active on the specified site:
.\Get-DelegateControls.ps1 http://publishing | ft Id, ControlClass, ControlSrc
Next you can query for all Delegate Controls registered with the specific place holder, eg:
.\Get-DelegateControls.ps1 http://publishing "AdditionalPageHead" -AllowMultiple | ft ControlClass, ControlSrc
Because the AdditionalPageHead place holder allows multiple controls we add the AllowMultiple switch to the script call. If you however wanted to retrieve the Delegate Control which is registered with a place holder that accepts only one control all you have to do is to remove the AllowMultiple switch from the call:
.\Get-DelegateControls.ps1 http://publishing "PublishingConsole" | ft ControlClass, ControlSrc
How it works
In order to retrieve the information about active Delegate Controls we have to search the definitions of all Features activated at all different scopes (lines 33-36). In every Feature Definition we look for the Control element (line 57) which is used to register Delegate Controls and we return every found match (line 58).
Summary
SharePoint 2010 ships with the Delegate Controls capability that allows users to extend standard functionality without changing the existing code. The downside of using Delegate Controls is that out of the box there is no overview of which controls have been registered with the site which makes it difficult to track reasons of errors caused by Delegate Controls. Using a simple PowerShell script and the SharePoint 2010 script it is possible to retrieve information about Delegate Controls that are active with the specific site what simplifies the debugging process.