Pages

Wednesday, July 27, 2011

Extending SharePoint STSADM Command Line Utility


Today I tried creating extending stsadm command line utility given by SharePoint platform and followed instructions specified on MSDN site, a very good article can be found here.
Sometimes we want to perform some tasks related to SharePoint sites , but somehow we end up with facing errors when done using UI , or some settings which explicitly need to be done using code behind. so instead writing number of console applications to execute these operations on server , this time I decided to write customer stsadm command.
Example below shows how we can change the culture of the web, I have already posted about this when I was doing this using console application so code remains the same but some modifications in the functions
First of all we need to understand how stsadm works, when you go to 12 hive folder you will see folder with name “CONFIG” . All the stsadm commands are kept in this location. so when you create your own commands then you need to have a definition file which we need to place in 12\CONFIG folder with naming convention like  stsadmcommands.sample.xml (note : word sample could be anything as you want).
then we need to have a class file which will act as code behind for the command. class should be inheriting from the OOB interface ISPStsadmCommand. Once this is done then we need to implement two methods of this interface in custom class
#region ISPStsadmCommand Members

string ISPStsadmCommand.GetHelpMessage(string command)
{
   throw new NotImplementedException();
}

int ISPStsadmCommand.Run(string command, StringDictionary keyValues, out string output)
{
    throw new NotImplementedException();
}

#endregion
Ok so far so good, before diving into the code, people might have question like, why one should create these for? And answer is,
There are some times when we want to perform certain operations on SP platform and we end up with writing number of customer console applications for each of those operations , this can simplify the approach as we can write bunch of commands in single file and use them.
Some good operation using stsadm (not available with OOB SP STSADM) are done by Gary lapointe, and you can take a look at those here.

Here is the definition file with syntax
<?xml version="1.0" encoding="utf-8" ?>
<commands>
<command name="setwebculture" class="MyCustomStsadmCommand.ChangeWebLocale,   MyCustomStsadmCommand,
  Version=1.0.0.0,
  Culture=neutral,
  PublicKeyToken=64622bec6a4399fa"/>
</commands>
and here is the code behind

namespace MyCustomStsadmCommand
{
 public class ChangeWebLocale : ISPStsadmCommand
 {
  #region ISPStsadmCommand Members

  public string GetHelpMessage(string command)
  {
     return "-url <full url to a root web in SharePoint Site Collection> -culturename -recursive";
  }

  public int Run(string command, StringDictionary keyValues, out string output)
  {
     command = command.ToLowerInvariant();

     switch (command)
     {
       case "setwebculture":
        return this.ChangeCulture(keyValues, out output);

       default:
         throw new InvalidOperationException();
      }

   }

   private int ChangeCulture(StringDictionary keyValues, out string output)
   {
     if (!keyValues.ContainsKey("url"))
     {
      throw new InvalidOperationException("The url parameter was not specified.");
     }
     if (!keyValues.ContainsKey("culturename"))
     {
      throw new InvalidOperationException("The CultureName parameter was not specified.");
     }

     String url = keyValues["url"];
     String cultureName = keyValues["culturename"];
     String recursive = keyValues["recursive"];
     bool _isRecursive = false;
     if (string.IsNullOrEmpty(recursive))
     {
       recursive = "False";
     }
     bool _IsRecursive = bool.TryParse(recursive, out _isRecursive);

     SPWeb web = null;
     StringBuilder sb = null;

     try
     {
       CultureInfo _cultureInfo = new CultureInfo(cultureName);
       sb = new StringBuilder();
       using (SPSite site = new SPSite(url))
        {
         using (web = site.OpenWeb())
         {
           if (_isRecursive)
           {
             RecursiveChangeCulture(web, _cultureInfo, sb);
           }
           else
           {
             web.AllowUnsafeUpdates = true;
             web.Locale = _cultureInfo;
             web.Update();
             web.AllowUnsafeUpdates = false;
             sb.AppendLine("culture changed for " + web.Title + " to " + _cultureInfo.EnglishName);
            }
          }
         }
      }
      catch (Exception ex)
      {
       throw new InvalidOperationException("Error Details: " + ex.Message);
      }

     output = sb.ToString();
     sb.Remove(0, sb.Length);
     return 0;
   }

 private void RecursiveChangeCulture(SPWeb web, CultureInfo _c, StringBuilder _sb)
 {
    if (web != null)
    {
     web.AllowUnsafeUpdates = true;
     CultureInfo _previousLocale = web.Locale;
     web.Locale = _c;
     _sb.AppendLine("culture changed for " + web.Title + " from " + _previousLocale.EnglishName + " to " + _c.EnglishName);
     web.Update();
     web.AllowUnsafeUpdates = false;

     foreach (SPWeb _web in web.Webs)
     {
         RecursiveChangeCulture(_web, _c, _sb);
     }
  }
 }

 #endregion
}
}


No comments:

Post a Comment