SharePoint Automation Gary Lapointe – Founding Partner, Aptillon, Inc.

3Dec/077

Set Usage Analysis

As part of our upgrade I wanted to make sure that usage analysis was fully enabled and configured so that site collection administrators could track how their sites were being used. As there was no built-in stsadm command to do this I had to create my own: gl-setusageanalysis. Turns out that setting the usage settings via code is simple until you get to the point where you want to configure the advanced usage analysis and logging which is an SSP level configuration. With most SSP configurations this one has no public interface - fortunately it's reasonably easy to use reflection to get at the code to make the change (a very simple method call - it's beyond me why this isn't made public - I'm starting to sound like a broken record but it's extremely frustrating). The code is shown below:

   1: public override int Run(string command, StringDictionary keyValues, out string output)
   2: {
   3:  output = string.Empty;
   4:  
   5:  InitParameters(keyValues);
   6:  
   7:  // Get the usage settings from the administration web service (basically the Central Administration web application)
   8:  SPUsageSettings usageSettings = SPWebService.AdministrationService.UsageSettings;
   9:  
  10:  if (Params["enablelogging"].UserTypedIn)
  11:   usageSettings.LoggingEnabled = bool.Parse(Params["enablelogging"].Value);
  12:  
  13:  if (Params["enableusageprocessing"].UserTypedIn)
  14:   usageSettings.UsageProcessingEnabled = bool.Parse(Params["enableusageprocessing"].Value);
  15:  
  16:  if (Params["logfilelocation"].UserTypedIn)
  17:   usageSettings.LogFilesDirectory = Params["logfilelocation"].Value;
  18:  
  19:  if (Params["numberoflogfiles"].UserTypedIn)
  20:   usageSettings.NumberLogFiles = uint.Parse(Params["numberoflogfiles"].Value);
  21:  
  22:  if (Params["processingstarttime"].UserTypedIn) // Validation makes sure that end time is also provided
  23:  {
  24:   DateTime startTime = DateTime.Parse(Params["processingstarttime"].Value);
  25:   DateTime endTime = DateTime.Parse(Params["processingendtime"].Value);
  26:   usageSettings.SetProcessingInterval(startTime.Hour, startTime.Minute, endTime.Hour, endTime.Minute);
  27:  }
  28:  usageSettings.Update();
  29:  
  30:  
  31:  if (Params["sspname"].UserTypedIn)
  32:  {
  33:   string sspname = Params["sspname"].Value;
  34:  
  35:   // The SSP is locked down so we need to use reflection to get at it.
  36:   object sharedResourceProvider = Utilities.GetSharedResourceProvider(sspname);
  37:  
  38:   if (Params["enableadvancedprocessing"].UserTypedIn)
  39:   {
  40:    Type configurationType = Type.GetType(
  41:      "Microsoft.SharePoint.Portal.Analytics.Configuration, Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
  42:    
  43:    bool enable = bool.Parse(Params["enableadvancedprocessing"].Value);
  44:    //Microsoft.SharePoint.Portal.Analytics.Configuration.SetAnalyticsEnabledOnSrp(sharedResourceProvider, enable);
  45:    Utilities.ExecuteMethod(configurationType, "SetAnalyticsEnabledOnSrp",
  46:          new Type[] {sharedResourceProvider.GetType(), typeof (bool)},
  47:          new object[] {sharedResourceProvider, enable});
  48:   }
  49:  
  50:   if (Params["enablequerylogging"].UserTypedIn)
  51:   {
  52:    Type queryLoggerType = Type.GetType(
  53:      "Microsoft.Office.Server.Search.Query.QueryLogger, Microsoft.Office.Server.Search, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
  54:    
  55:    bool enable = bool.Parse(Params["enablequerylogging"].Value);
  56:    //Microsoft.Office.Server.Search.Query.QueryLogger.SetQueryLoggingEnabledOnSsp(sharedResourceProvider, enable);
  57:    Utilities.ExecuteMethod(queryLoggerType, "SetQueryLoggingEnabledOnSsp",
  58:          new Type[] {sharedResourceProvider.GetType(), typeof (bool)},
  59:          new object[] {sharedResourceProvider, enable});
  60:   }
  61:  
  62:   Console.WriteLine("The settings updated may require an iisreset before the changes are visible.");
  63:  }
  64:  
  65:  return 1;
  66: }

The syntax of the command can be seen below:

C:\>stsadm -help gl-setusageanalysis

stsadm -o gl-setusageanalysis

Sets the usage analysis settings.

Parameters:
        [-enablelogging <true | false>]
        [-enableusageprocessing <true | false>]
        [-logfilelocation <log file location>]
        [-numberoflogfiles <number of log files to create (0-30)>]
        [-processingstarttime <usage analysis start time>]
        [-processingendtime <usage analysis end time>]
        [-sspname <SSP name>]
        [-enableadvancedprocessing <true | false>]
        [-enablequerylogging <true | false>]
Here's an example of how to enable usage analysis:
stsadm -o gl-setusageanalysis -enablelogging true -enableusageprocessing true -logfilelocation "c:\Logs" -numberoflogfiles 30 -processingstarttime "10:00PM" -processingendtime "1:00AM" -sspname SSP1 -enableadvancedprocessing true -enablequerylogging true
If you've changed any of the SSP related parameters then you may need to do an IIS reset before the changes show up in the browser.

30Nov/077

Set Audit Settings for Site Collection

In any financial institution auditing is crucial - it's no different with my company - as such we wanted to make sure that there was at least a minimum level of auditing occurring at the site collection level. From the site collection settings page you can get to the "Site collection audit settings" page where some basic auditing can be enabled. For more complex stuff you can setup custom policies and associate them at various levels. However, for our initial deployment we wanted to at least have some of these basic settings enabled for every site collection. To automate these settings during our upgrade I created a new command: gl-setauditsettings. This command turned out to be really easy to create and only took me a few minutes. Only thing I stumbled on was figuring out the best way to handle replacing, adding, or removing settings so that I didn't have to create more than one command. In the end I opted for a simple mode parameter which enables you to state your intent - each setting is then a simple parameter that's passed in. The code, shown below, gets the SPAudit object via the SPSite's Audit property and then sets the AuditFlags property appropriately:

   1: public override int Run(string command, StringDictionary keyValues, out string output)
   2: {
   3:  output = string.Empty;
   4:  
   5:  InitParameters(keyValues);
   6:  
   7:  string url = Params["url"].Value.TrimEnd('/');
   8:  ModeEnum mode = (ModeEnum) Enum.Parse(typeof (ModeEnum), Params["mode"].Value, true);
   9:  
  10:  using (SPSite site = new SPSite(url))
  11:  {
  12:   // Initialize the mask to it's default.
  13:   SPAuditMaskType auditMask = SPAuditMaskType.None;
  14:   if (mode != ModeEnum.Replace)
  15:    auditMask = site.Audit.AuditFlags; // We're not replacing the mask so we need to store the current settings.
  16:  
  17:   if (mode == ModeEnum.Remove)
  18:   {
  19:    // Remove settings
  20:    foreach (SPAuditMaskType mask in Enum.GetValues(typeof(SPAuditMaskType)))
  21:    {
  22:     if (Params[mask.ToString()].UserTypedIn)
  23:      auditMask = auditMask & ~mask;
  24:    }
  25:   }
  26:   else
  27:   {
  28:    // Add settings (replace is just an add but starts with a blank slate)
  29:    foreach (SPAuditMaskType mask in Enum.GetValues(typeof(SPAuditMaskType)))
  30:    {
  31:     if (Params[mask.ToString()].UserTypedIn)
  32:      auditMask = auditMask | mask;
  33:    }
  34:   }
  35:   // Update the Audit object with the new flags
  36:   site.Audit.AuditFlags = auditMask;
  37:   site.Audit.Update();
  38:  }
  39:  
  40:  return 1;
  41: }

The syntax of the command can be seen below:

C:\>stsadm -help gl-setauditsettings

stsadm -o gl-setauditsettings

Set the events that should be audited for documents, items, lists, libraries, and sites within the site collection.

Parameters:
        -url <site collection url>
        -mode <replace | add | remove>
        [-none]
        [-checkout]
        [-checkin]
        [-view]
        [-delete]
        [-update]
        [-profilechange]
        [-childdelete]
        [-schemachange]
        [-securitychange]
        [-undelete]
        [-workflow]
        [-copy]
        [-move]
        [-search]
        [-all]
Here's an example of how to enable auditing of the delete and undelete events in addition to any existing events already monitored:
stsadm -o gl-setauditsettings -url "http://intranet" -mode add -delete -undelete
One thing to be aware of - when you edit these settings via the browser you are, in some circumstances, editing more than one setting at a time. For example, via the browser you cannot choose to audit delete events and not undelete events - they are combined into one setting. Using this command allows you to set the audit settings at a finer level so you can track just delete events without tracking undelete (in most cases you'll want to track both but it's nice to know that you can now treat them separately). Note however that if you use this command to enable just delete and not undelete the browser will show the check box for "Deleting or restoring items" as checked as it does an or comparison when enabling the check box.