Showing posts with label SPFarm. Show all posts
Showing posts with label SPFarm. Show all posts

Monday, April 20, 2009

Programmatically Activating Features just after Deployment

There are a variety of scenarios where features need to be programmatically activated just after a solution has been deployed.  I have found that even when the SPSolution object says it has been deployed, it really isn’t finished deploying.  Sometimes my SPFeatureDefinitions are either non existents or not installed even when the deployment is “done”.  They eventually do show up. Until they do, feature activation fails when the feature is added to the SPFeatureCollection of the SPFarm, SPWebApplication, SPSite, or SPWeb.  I ended up coding a small bit of code to work around this problem.  This example shows activation of a web application scope feature, but the algorithm can be applied to a feature of any scope.

private void ActivateWebApplicationFeature(Uri webApplicaitonUri, Guid featureId, int timeoutSeconds)
{
    const int sleepTime = 1000;
    for (int i = 0; i < timeoutSeconds; i++)
    {
        try
        {
            SPFeatureDefinition definition = SPFarm.Local.FeatureDefinitions[featureId];
            if (definition.Status == SPObjectStatus.Online)
            {
                break;
            }
            Thread.Sleep(sleepTime);
        }
        catch
        {
            Thread.Sleep(sleepTime);
        }
    }
    SPWebApplication application = SPWebApplication.Lookup(webApplicaitonUri);
    if (application.Features[featureId] == null)
    {
        AddWebApplicationFeature(webApplicaitonUri, featureId);
    }
}

private void AddWebApplicationFeature(string webApplicaitonUri, Guid featureId)
{
    int count = 0;
    while (true)
    {
        try
        {
            SPWebApplication application = SPWebApplication.Lookup(webApplicaitonUri);
            application.Features.Add(featureId);
            application.Update();
            break;
        }
        catch (SPDeletedConcurrencyException)
        {
            // Done. This object is gone so we are finished.
            // Optional logging of condition
            break;
        }
        catch (SPUpdatedConcurrencyException)
        {
            count++;
            if (count > 10)
            {
                throw;
            }
        }
    }
}

The algorithm is to first wait for the feature definition to appear.   When looking up the SPFeatureDefinition in the SPFeatureDefinitionCollection an exception will be thrown until the definition has been added.  The code waits a second between checks.  It continues waiting for the SPFeatureDefinition to install.  Finally it activates the feature if the feature needs activation (in certain upgrade scenarios the feature may already be active).  You will notice that the second method uses my technique to control SPDeletedConcurrencyException and SPUpdatedConcurrencyException

Wednesday, April 1, 2009

Who is "The Farm Administrator"

New SharePoint developers can often be confused about farm administration.  In the Central Administration -> Operations -> Update Farm Administrators there are a list of users who are farm administrators.  These users are farm administrators but they are not “The Farm Administrator.”  This is actually a wrapper on the local operating system group WSS_ADMIN_WPG which has the description: “Members of this group have write access to system resources used by Windows SharePoint Services.” The group exists locally on each server in the farm and the Central Administration application propagates changes to all servers in the farm.

If you wish to know who is “The Farm Administrator” you need to look at the local group WSS_RESTRICTED_WPG.  This group has the description: “Group for the Windows SharePoint Services farm administrator.” Normally this group contains one and only one user.  This should be the same user that was entered in “Specify Database Access Account” in the “Advanced” SharePoint configuration path.  It is also the same user used for the Central Administration Application Pool  as well as the Timer Service process. Any time a SharePoint object is updated by this user will be marked as changed by “SHAREPOINT\system”. This is “The Farm Administrator.” For the “Basic” SharePoint configuration path this user is always NT AUTHORITY\NETWORK SERVICE. This user is called the “Server farm account” in Microsoft’s Office SharePoint Server security account requirements document.

There is an erroneous perception amongst new SharePoint programmers that this user is all powerful.  This is not quite true.  Here are the facts.

Does “The Farm Administrator” have operating system administration rights on each of the SharePoint servers? NO. If configured correctly (for best security) this user has no power outside of the SharePoint domain.

Does “The Farm Administrator” have read and write rights on all site collections in SharePoint? NO. If configured correctly (for best security) this user does not have direct access to business data. That access has been delegated to the site collection administrators.  There are several methods of indirect access (1) (2), but there is no assumption that any farm administrator can simply ask for any Site or Web in the system.

There is one last group worth mention in this article.  The local WSS_WPG group which has the description: “Members of this group have read access to system resources used by Windows SharePoint Services.” The process users who run SharePoint services are added to this group.  This includes the web application pool users as well as any windows service that SharePoint oversees.

 

Friday, March 6, 2009

SPPersistedObject.Properties is a great place for storing miscellaneous data

The SPPersistedObject.Properties  property is a great place to store miscellaneous data and place flags on administrative objects.  There are two very important considerations when using this data store.

1. Although it is implemented by a System.Collections.Hashtable which can take any object as a key.  The only acceptable key in SharePoint is a string key.  Using any other object class will cause SharePoint to throw spurious class cast exceptions. The Microsoft.SharePoint.Administration.SPBackwardCompatibilityPropertyMapper.GetClusterProperties() is one such internal method that will throw System.InvalidCastException if your SPFarm.Properties contain non-string keys.

2. Remember to call Update after adding or removing a key/value pair in the Hashtable.  It is easy to miss this and I have found that it is often not detected in unit tests.  The following are SharePoint singleton objects within a given process: SPAdministrationWebApplication.Local, SPDiagnosticService.Local, SPFarm.Local, SPFarm.Local.TimerService, SPServer.Local, SPWebService.ContentService, SPWebService.AdministrationService,  SPWebServiceInstance.LocalAdministration, and SPWebServiceInstance.LocalContent.  In most unit tests both the operations performed and the asserts called occur in the same process.  If you are setting properties on these singleton objects within your unit test process, there is no way to tell whether those properties were persisted back to the database.  The only way to detect it would be to use a two process test harness.